bzoj3237 [Ahoi2013]连通图
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
1 2
2 3
3 4
4 1
2 4
3
1 5
2 2 3
2 1 2
Sample Output
Connected
Disconnected
Connected
Disconnected
Connected
HINT
N<=100000 M<=200000 K<=100000
正解:$CDQ$分治+并查集。
我来学习一波$CDQ$图分治。。其实很简单,我们只要在分治$[l,r]$的时候连上$[l,r]$都有的边就行了。
当$l=r$的时候判断一下那$4$个不连的边对应的点是否连通就行了。
复杂度为什么是对的呢?我们注意到一条边一定是覆盖了一个区间,而分治的时候区间不超过$logn$个,于是每条边最多只会被连$logn$次。复杂度就是$O(mlogn)$的。
但是我们还要用并查集,且并查集必须支持撤回,于是我们开个栈记录一下被覆盖掉的父子关系就行了,然后复杂度变成了$O(mlog^{2}n)$。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define inf (1<<30) 14 #define N (200010) 15 #define il inline 16 #define RG register 17 #define ll long long 18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 19 20 using namespace std; 21 22 struct edge{ int u,v; }g[N]; 23 24 int ans[N],fa[N],vis[N],st[25*N],q[N][5],n,m,k,tim,top; 25 26 il int gi(){ 27 RG int x=0,q=1; RG char ch=getchar(); 28 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 29 if (ch=='-') q=-1,ch=getchar(); 30 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 31 return q*x; 32 } 33 34 il int find(RG int x){ 35 if (fa[x]==x) return x; 36 st[++top]=x,st[++top]=fa[x]; 37 return fa[x]=find(fa[x]); 38 } 39 40 il void unionn(RG int u,RG int v){ 41 if (find(u)!=find(v)){ 42 st[++top]=fa[u]; 43 st[++top]=fa[fa[u]]; 44 fa[fa[u]]=fa[v]; 45 } 46 return; 47 } 48 49 il void solve(RG int l,RG int r){ 50 RG int mid=(l+r)>>1,now=top,flag=1; ++tim; 51 if (l==r){ 52 for (RG int i=1;i<=q[l][0] && flag;++i) 53 if (find(g[q[l][i]].u)!=find(g[q[l][i]].v)) flag=0; 54 for (;top>now;top-=2) fa[st[top-1]]=st[top]; ans[l]=flag; return; 55 } 56 for (RG int i=l;i<=mid;++i) 57 for (RG int j=1;j<=q[i][0];++j) vis[q[i][j]]=tim; 58 for (RG int i=mid+1;i<=r;++i) 59 for (RG int j=1;j<=q[i][0];++j) 60 if (vis[q[i][j]]!=tim) unionn(g[q[i][j]].u,g[q[i][j]].v); 61 solve(l,mid),++tim; for (;top>now;top-=2) fa[st[top-1]]=st[top]; 62 for (RG int i=mid+1;i<=r;++i) 63 for (RG int j=1;j<=q[i][0];++j) vis[q[i][j]]=tim; 64 for (RG int i=l;i<=mid;++i) 65 for (RG int j=1;j<=q[i][0];++j) 66 if (vis[q[i][j]]!=tim) unionn(g[q[i][j]].u,g[q[i][j]].v); 67 solve(mid+1,r); for (;top>now;top-=2) fa[st[top-1]]=st[top]; return; 68 } 69 70 il void work(){ 71 n=gi(),m=gi(),tim=1; for (RG int i=1;i<=n;++i) fa[i]=i; 72 for (RG int i=1;i<=m;++i) g[i].u=gi(),g[i].v=gi(); k=gi(); 73 for (RG int i=1;i<=k;++i){ 74 q[i][0]=gi(); 75 for (RG int j=1;j<=q[i][0];++j) q[i][j]=gi(),vis[q[i][j]]=tim; 76 } 77 for (RG int i=1;i<=m;++i) if (!vis[i]) unionn(g[i].u,g[i].v); solve(1,k); 78 for (RG int i=1;i<=k;++i) puts(ans[i] ? "Connected" : "Disconnected"); return; 79 } 80 81 int main(){ 82 File("graph"); 83 work(); 84 return 0; 85 }