bnuoj 51275 道路修建 並查集按秩合併

2021-07-09 23:30:48 字數 1794 閱讀 5043

題意:維護乙個並查集,但需要詢問2個點是在第幾次操作後連通的。

直接可持久化並查集應該行,

但更簡單的方法是,把並查集按秩合併,

即t時刻,在u,v所處連通塊間連一條權值為t的邊,

這樣每個並查集的樹高是log級的。

#include

using namespace std;

#define for(i,n) for(int i=1;i<=n;i++)

#define fork(i,k,n) for(int i=k;i<=n;i++)

#define rep(i,n) for(int i=0;i#define ford(i,n) for(int i=n;i;i--)

#define forkd(i,k,n) for(int i=n;i>=k;i--)

#define repd(i,n) for(int i=n;i>=0;i--)

#define forp(x) for(int p=pre[x];p;p=next[p])

#define forpiter(x) for(int &p=iter[x];p;p=next[p])

#define lson (o<<1)

#define rson ((o<<1)+1)

#define mem(a) memset(a,0,sizeof(a));

#define memi(a) memset(a,127,sizeof(a));

#define memi(a) memset(a,128,sizeof(a));

#define inf (2139062143)

#define f (100000007)

#define pb push_back

#define mp make_pair

#define fi first

#define se second

#define vi vector

#define pi pair

#define si(a) ((a).size())

typedef long

long ll;

typedef unsigned long

long ull;

ll mul(ll a,ll b)

ll add(ll a,ll b)

ll sub(ll a,ll b)

void upd(ll &a,ll b)

int read()

while(isdigit(ch))

return x*f;

} #define maxn (100000+10)

#define maxm (500000+10)

class bingchaji

int getfather(int x)

bool unite(int x,int y,int t)

else

return

1; }

int query(int x,int y)

p=y; cost=0;

int res=0;

while (1)

if (p==father[p]) break;

cost=max(cost,tcn[p]);

p=father[p];

}p=x;

while (1)

return res;

} }s;int main()

else

}

}return

0;}

並查集 按秩合併 路徑壓縮

一種可以動態維護若干個不重疊的集合或無向圖的連通塊的資料結構。主要支援以下操作 find 查詢乙個元素屬於哪個集合 merge 合併兩個集合 並查集的每個集合都需要乙個 爹 來表示這整個集合,所以判斷兩個元素是否在同一集合,就看他們爹是否相同。有乙個顯而易見的初始化,對於要維護的序列,初始每個元素的...

並查集(路徑壓縮 按秩合併) 總結

就是連邊,然後,每次問你兩個點是否可互通。為無向邊 然後,暴力的話可能就是一條鏈下來,搞爆了。所以我們要想想優化。個人覺得這個比較好理解,很早便學會了,而且速度要優秀一些。就是將連了邊的同時指向乙個人 自擬的祖宗 然後,每次查詢的時候就壓縮一下路徑。具體是這樣來搞的 intgf int x intm...

BZOJ4668 冷戰 並查集 按秩合併

題意 還可以這樣亂搞 並查集按秩合併的好處 深度不會超過 o log n 樹的結構保持較穩定 雖說連邊的時候依舊是祖先來連邊,但連邊不會改變原來的結構,並且 u,v 路徑上會經過新連的邊 於是就可以亂搞了 維護乙個按秩合併的並查集,給連邊操作加時間戳,查詢的時候暴力求路徑上時間戳最大值 ps 暴力l...