hdu 5458 樹鏈剖分模板

2021-07-13 13:41:05 字數 2788 閱讀 1254

題意:給出一張n個點,m條邊的無向圖,有兩個操作:

1.刪除(u, v)間的一條邊

2.如果刪除(u, v)間的一條邊可使其不連通,找出這樣的邊的個數,就是找(u, v)間橋的個數

思路:首先離線這些操作,時光倒流從最終狀態逆著加邊加回原圖,可以考慮用並查集建樹,然後以樹作為最終狀態,再樹鏈剖分預處理下,建一顆線段樹維護區間和(葉子值為1代表當前邊為橋),如果有邊(u, v)要加入,那就將(u, v)這段區間的所對應的線段樹葉子值全清零,並設定標記陣列,因為已更新過的點不用再訪問

#include 

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define lson l, mid, rt << 1

#define rson mid + 1, r, rt << 1 | 1

#pragma comment(linker, "/stack:102400000,102400000")

using

namespace

std;

typedef

long

long ll;

const

int maxn = 101000;

const

int inf = 0x3f3f3f3f;

struct edge

edge[maxn << 1];

int head[maxn], tot, val[maxn];

int top[maxn], fa[maxn], deep[maxn];

int num[maxn], p[maxn], fp[maxn];

int son[maxn], pos, mp[maxn];

void init()

void addedge(int u, int v)

void dfs1(int u, int pre, int d)

}}void getpos(int u, int sp)

}struct uf

int find(int x)

} uf;

map ma[maxn];

map ::iterator it;

int tr[maxn << 2], lazy[maxn << 2];

void pushup(int rt)

void build(int l, int r, int rt)

int mid = (l + r) >> 1;

build(lson);

build(rson);

pushup(rt);

}void update(int ql, int qr, int l, int r, int rt)

int mid = (l + r) >> 1;

if (ql <= mid)

update(ql, qr, lson);

if (qr > mid)

update(ql, qr, rson);

pushup(rt);

}int query(int ql, int qr, int l, int r, int rt)

void change(int u, int v)

update(p[fu], p[u], 1, pos, 1);

u = fa[fu], fu = top[u];

}if (deep[u] > deep[v]) swap(u, v);

if (u != v)

update(p[son[u]], p[v], 1, pos, 1);

}int answer(int u, int v)

res += query(p[fu], p[u], 1, pos, 1);

u = fa[fu], fu = top[u];

}if (deep[u] > deep[v]) swap(u, v);

if (u != v)

res += query(p[son[u]], p[v], 1, pos, 1);

return res;

}struct node

que[maxn];

int main()

for (int i = 1; i <= q; i++)

for (int i = 1; i <= n; i++)}}

}dfs1(1, 0, 0);

getpos(1, 1);

build(1, pos, 1);

// for (int i = 0; i < tot; i += 2)

// printf("%d %d\n", edge[i].from, edge[i].to);

// for (int i = 1; i <= n; i++)

// printf("%d\n", p[i]);

for (int i = 1; i <= n; i++)}}

for (int i = q; i >= 1; i--)

for (int i = 1; i <= q; i++)

if (que[i].op == 2)

printf("%d\n", que[i].ans);

}return

0;}

HDU 5458(樹鏈剖分)

題意 給乙個無向圖,兩種操作,刪除一條邊,詢問兩點之間關鍵路徑的數目。關鍵路徑,即刪除這條邊,兩點就不聯通了。保證圖一直聯通。解法 先在最後的圖上跑一顆生成樹。每有一條其他的邊,就對路徑上的所有邊 1。所以就存在兩種操作,對某一段 1,查詢某一段上0的個數,就可以用線段樹做了。pragma comm...

樹鏈剖分 模板

class match node a n struct no no aa n 4 void init void addpage int x,int y void dfs int s,int faa,int h 根節點,父節點和深度的 if max 0 son s sign void dfs2 int...

模板 樹鏈剖分

define maxn 50010 define l u u 1 define r u u 1 1 寫在類裡面爆棧 int n,m,q int tim 時間戳 int num maxn 樹上每個節點的初始值 int siz maxn siz u 表示以u為根的子樹的節點數 int top maxn ...