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
解题思路:
注意到原图是一个连通图,所以我们判断一个集合的答案时只用判断其包含的边的两端是否连通即可。
考虑分治。首先连上所有集合中都没有的边。
对于左边的集合,先连上这些集合中没有而右边集合中有的边,递归处理。
对于右边的集合,先连上这些集合中没有而左边集合中有的边,递归处理。
到底层时判断该集合答案即可。
连通性肯定要用并查集维护,但这题递归后要撤销连边,所以用可持久化并查集或栈式并查集都可以。
#include<bits/stdc++.h>
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=200005,M=5000005;
int n,m,Q,idx,top,fa[N],ans[N],stk1[M],stk2[M];
struct edge{int x,y,idx;}e[N];
struct node{int cnt,c[5];}q[N];
int find(int x)
{
if(x==fa[x])return x;
int y=find(fa[x]);
if(y!=fa[x])stk1[++top]=x,stk2[top]=fa[x],fa[x]=y;
return y;
}
void solve(int l,int r)
{
int Top=top;
if(l==r)
{
for(int i=1;i<=q[l].cnt;i++)
if(find(e[q[l].c[i]].x)!=find(e[q[l].c[i]].y)){ans[l]=0;break;}
return;
}
int mid=l+r>>1;++idx;
for(int i=l;i<=mid;i++)
for(int j=1;j<=q[i].cnt;j++)e[q[i].c[j]].idx=idx;
for(int i=mid+1;i<=r;i++)
for(int j=1;j<=q[i].cnt;j++)
if(e[q[i].c[j]].idx!=idx)
{
int x=find(e[q[i].c[j]].x),y=find(e[q[i].c[j]].y);
if(x!=y)stk1[++top]=x,stk2[top]=fa[x],fa[x]=y;
}
solve(l,mid);
while(top!=Top)fa[stk1[top]]=stk2[top],--top;
++idx;
for(int i=mid+1;i<=r;i++)
for(int j=1;j<=q[i].cnt;j++)e[q[i].c[j]].idx=idx;
for(int i=l;i<=mid;i++)
for(int j=1;j<=q[i].cnt;j++)
if(e[q[i].c[j]].idx!=idx)
{
int x=find(e[q[i].c[j]].x),y=find(e[q[i].c[j]].y);
if(x!=y)stk1[++top]=x,stk2[top]=fa[x],fa[x]=y;
}
solve(mid+1,r);
while(top!=Top)fa[stk1[top]]=stk2[top],--top;
}
int main()
{
//freopen("lx.in","r",stdin);
n=getint(),m=getint();
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++)e[i].x=getint(),e[i].y=getint();
Q=getint();++idx;
for(int i=1;i<=Q;i++)
{
q[i].cnt=getint();ans[i]=1;
for(int j=1;j<=q[i].cnt;j++)
e[q[i].c[j]=getint()].idx=idx;
}
for(int i=1;i<=m;i++)
if(e[i].idx!=idx)
fa[find(e[i].x)]=find(e[i].y);
solve(1,Q);
for(int i=1;i<=Q;i++)ans[i]?puts("Connected"):puts("Disconnected");
return 0;
}