1. 程式人生 > >[BZOJ3237]連通圖

[BZOJ3237]連通圖

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

自己yy的奇怪解法,首先我們可以發現一張圖在聯通的時候並查集祖先的$size=n$(這不是廢話)

然後就只要線段樹分治隨便維護一下並查集就完事了

程式碼:

 1 #include<iostream>
 2
#include<cstdio> 3 #include<cstring> 4 #include<vector> 5 #include<map> 6 #define ls node<<1 7 #define rs node<<1|1 8 #define M 200010 9 #define mod 1000000007 10 using namespace std; 11 struct point{int u,v;}p[M],st[M]; 12 int n,m,k,top; 13 int size[M],fa[M],f[M];
14 vector<int>tag[M<<2]; 15 int find(int x) { 16 while(x!=fa[x]) x=fa[x]; 17 return fa[x]; 18 } 19 void insert(int node,int l,int r,int l1,int r1,int id) { 20 if(l1<=l&&r1>=r) { 21 tag[node].push_back(id);return; 22 }int mid=(l+r)/2; 23 if
(l1<=mid) insert(ls,l,mid,l1,r1,id); 24 if(r1>mid) insert(rs,mid+1,r,l1,r1,id); 25 } 26 void unionn(int x,int y) { 27 x=find(x),y=find(y); 28 if(x==y) return; 29 if(size[x]<size[y]) swap(x,y); 30 st[++top]=(point){x,y}; 31 size[fa[y]=x]+=size[y]; 32 } 33 void Del(int now) { 34 while(top!=now) { 35 int x=st[top].u,y=st[top--].v; 36 size[x]-=size[fa[y]=y]; 37 } 38 } 39 void Dfs(int node,int l,int r) { 40 int now=top; 41 for(int i=0;i<tag[node].size();i++) 42 unionn(p[tag[node][i]].u,p[tag[node][i]].v); 43 if(l==r) { 44 int x=1; 45 while(fa[x]!=x) x=fa[x]; 46 puts(size[x]==n?"Connected":"Disconnected"); 47 } 48 else { 49 int mid=(l+r)/2; 50 Dfs(ls,l,mid),Dfs(rs,mid+1,r); 51 } 52 Del(now); 53 } 54 int main() { 55 scanf("%d%d",&n,&m); 56 for(int i=1;i<=n;i++) fa[i]=i,size[i]=1; 57 for(int a,b,i=1;i<=m;i++) { 58 scanf("%d%d",&a,&b);f[i]=1; 59 p[i]=(point){a,b}; 60 } 61 scanf("%d",&k); 62 for(int i=1;i<=k;i++) { 63 int c;scanf("%d",&c); 64 for(int j=1;j<=c;j++) { 65 int id;scanf("%d",&id); 66 if(f[id]!=i) insert(1,1,k,f[id],i-1,id); 67 f[id]=i+1; 68 } 69 } 70 for(int i=1;i<=m;i++) 71 if(f[i]!=k+1) 72 insert(1,1,k,f[i],k,i); 73 Dfs(1,1,k); 74 return 0; 75 }