BZOJ3319 黑白樹 並查集

2022-05-20 09:59:28 字數 1184 閱讀 2132

給定一棵樹,邊的顏色為黑或白,初始時全部為白色。維護兩個操作:

1.查詢u到根路徑上的第一條黑色邊的標號。

2.將u到v    路徑上的所有邊的顏色設為黑色。

notice:這棵樹的根節點為1

第一行兩個數n,m分別表示點數和運算元。

接下來n-?    1行,每行2個數u,v.表示一條u到v的邊。

接下來m行,每行為以下格式:

1 v 表示第乙個操作

2 v u 表示第二種操作

對於每個詢問,輸出相應答案。如果不存在,輸出0。

5 41 2

1 32 4

2 51 2

2 2 3

1 31 402

1對於    100%    的資料:n,m<=10^6

題解:本題要用到兩邊並查集。

先用並查集預處理出每條邊第一次變黑的時間,然後時間倒流。如果這個點是白點,則將該點的並查集與其父親的並查集合並;如果是黑點則不合併。這樣,每個點所在的並查集的根節點的邊就是路徑上第乙個黑邊。

#include #include #include using namespace std;

const int maxn=1000010;

int n,m,cnt;

int to[maxn<<1],next[maxn<<1],head[maxn],vis[maxn],f[maxn],v[maxn];

int dep[maxn],fa[maxn],son[maxn],top[maxn],siz[maxn],q[maxn],ans[maxn];

inline int rd()

while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();

return ret*f;

}void add(int a,int b)

void dfs1(int x)

}void dfs2(int x,int tp)

int lca(int x,int y)

} for(i=1;i<=n;i++) f[i]=!vis[i]?fa[i]:i;

for(i=m;i>=1;i--)

for(i=1;i<=m;i++) if(q[i]) printf("%d\n",ans[i]);

return 0;

}

BZOJ3712 Fiolki(並查集重構樹)

bzoj 很神仙的題目。我們發現所有的合併關係構成了一棵樹。那麼兩種不同的東西如果產生反應,一定在兩個聯通塊恰好聯通的時候反應。那麼,我們按照並查集的合併順序,類似於克魯斯卡爾重構樹的方法構建乙個並查集重構樹,發現所有的反應恰好在兩者的 lca 處發生,所以把所有可以發生的翻譯拿出來,按照 lca ...

偶數樹 並查集

給你一棵有n個節點的樹 乙個無環簡單圖 節點序號為1 n,根節點為1。請你找出乙個最大的整數k,表示從這棵樹上斷掉k條邊使其所有的子樹的節點數都為偶數。第一行輸入兩個整數n,m。表示這棵樹有n個節點和m條邊。接下來有m行,每行輸入兩個整數u,v,表示u節點和v節點間有一條邊相連。資料保證 2 n 1...

BZOJ5005 桌球遊戲 線段樹 並查集

如果乙個區間的端點在區間內,則這個區間可以走到那個區間,詢問乙個區間能否到另乙個區間。首先我們立馬想到了 如果兩個區間嚴格有交集,那麼這兩個區間所能到達的區間集合是一樣的。那麼如果兩個區間嚴格有交集的話我們就可以把它們合併起來,這裡運用並查集。這樣處理完之後,剩下的區間只有兩種情況 包含或者相離。那...