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

Sample Output

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 }

 

posted @ 2017-06-09 09:22  wfj_2048  阅读(248)  评论(0编辑  收藏  举报