1. 程式人生 > >[BZOJ3237][AHOI2013]連通圖(分治並查集)

[BZOJ3237][AHOI2013]連通圖(分治並查集)

break freopen spa width eight line sca rip urn

3237: [Ahoi2013]連通圖

Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 1736 Solved: 655
[Submit][Status][Discuss]

Description

技術分享圖片

Input

技術分享圖片

Output

技術分享圖片

Sample Input

4 5
1 2
2 3
3 4
4 1
2 4
3
1 5
2 2 3
2 1 2

Sample Output



Connected
Disconnected
Connected

HINT


N<=100000 M<=200000 K<=100000

Source

[Submit][Status][Discuss]

在線LCT,離線CDQ。

考慮怎麽使用CDQ,對於區間[L,R],先將不在[L,mid]而在[mid+1,R]中的邊加入,遞歸到左半邊,撤銷,將不在[mid+1,R]而在[L,mid]中的邊加入,再次遞歸,撤銷。

一般帶撤銷並查集是不能路徑壓縮的,但其實壓縮了也沒關系,記錄壓縮之前的父親就好。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4
#define rep(i,l,r) for (int i=l; i<=r; i++) 5 typedef long long ll; 6 using namespace std; 7 8 const int N=200100,M=5000100; 9 struct P{ int u,v,tim; }e[N]; 10 struct Q{ int c[5],cnt; }q[N]; 11 int top,n,m,T,tim,u,v,f[N],ans[N],stk1[M],stk2[M]; 12 13 int find(int x){ 14 if (f[x]==x) return
x; 15 int y=find(f[x]); 16 if (y!=f[x]) stk1[++top]=x,stk2[top]=f[x],f[x]=y; 17 return y; 18 } 19 20 void solve(int l,int r){ 21 int Top=top; 22 if (l==r){ 23 int flag=1; 24 rep(i,1,q[l].cnt) 25 if (find(e[q[l].c[i]].u)!=find(e[q[l].c[i]].v)) 26 { flag=0; break; } 27 ans[l]=flag; 28 while (top!=Top) f[stk1[top]]=stk2[top],top--; 29 return; 30 } 31 int mid=(l+r)>>1; tim++; 32 rep(i,l,mid) rep(j,1,q[i].cnt) e[q[i].c[j]].tim=tim; 33 rep(i,mid+1,r) rep(j,1,q[i].cnt){ 34 int x=q[i].c[j]; 35 if (e[x].tim!=tim){ 36 int u=find(e[x].u),v=find(e[x].v); 37 if (u!=v) stk1[++top]=u,stk2[top]=f[u],f[u]=v; 38 } 39 } 40 solve(l,mid); tim++; 41 while (top!=Top) f[stk1[top]]=stk2[top],top--; 42 rep(i,mid+1,r) rep(j,1,q[i].cnt) e[q[i].c[j]].tim=tim; 43 rep(i,l,mid) rep(j,1,q[i].cnt){ 44 int x=q[i].c[j]; 45 if (e[x].tim!=tim){ 46 int u=find(e[x].u),v=find(e[x].v); 47 if (u!=v) stk1[++top]=u,stk2[top]=f[u],f[u]=v; 48 } 49 } 50 solve(mid+1,r); 51 } 52 53 int main(){ 54 freopen("bzoj3237.in","r",stdin); 55 freopen("bzoj3237.out","w",stdout); 56 scanf("%d%d",&n,&m); tim=1; 57 rep(i,1,m) scanf("%d%d",&e[i].u,&e[i].v); 58 scanf("%d",&T); 59 rep(i,1,T){ 60 scanf("%d",&q[i].cnt); int x; 61 rep(j,1,q[i].cnt) scanf("%d",&x),q[i].c[j]=x,e[x].tim=tim; 62 } 63 rep(i,1,n) f[i]=i; 64 rep(i,1,m) if (e[i].tim!=tim){ 65 int u=find(e[i].u),v=find(e[i].v); 66 if (u!=v) f[u]=v; 67 } 68 solve(1,T); 69 rep(i,1,T) if (ans[i]) puts("Connected"); else puts("Disconnected"); 70 return 0; 71 }

[BZOJ3237][AHOI2013]連通圖(分治並查集)