对于这题先套路的找出一棵生成树,然后还会剩下一些非树边,要删边使得图不连通(假设先删非树边)当且仅当删掉了一条没有返祖边覆盖的树边,或者是删了两条被相同的非树边集合覆盖的树边
现在要处理这个问题.我们给所有非树边一个随机权值,然后树边的权值就是覆盖它的非树边权值异或和,这个可以树上差分实现,那么两条树边如果异或和相等就认为覆盖它们的非树边集合相同,如果一条树边异或和为0就认为没有被覆盖.如果我们的随机的值域为\(2^w\),那么出错的概率就是\(\frac{1}{2^w}\),因为一个数只有正好选中一个对应的数才会出错
先给结论.对于给出的一个边集,删掉以后不连通,当且仅当这个边集中有一个子集权值异或和为0.接下来是感性证明:如果这个子集全是非树边那应该就在别的地方直接WA了;如果有一个是树边,也就是选出来的其他非树边都是覆盖它的,所以删掉后会不连通;如果有\(\ge 2\)个树边,那么一定可以把其他非树边分别异或到树边上去,使得有两个树边异或和相同.顺便再推荐一波理性证明.所以实现可以用线性基,做到出现线性相关的子集就可以不连通
#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define db double
using namespace std;
const int N=1e5+10;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int to[N*10],nt[N*10],hd[N],tot=1;
void add(int x,int y)
{
++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
}
int n,m,q,fa[N],de[N],sz[N],hs[N],top[N];
uLL a[N],w[N*5],bs[70];
bool vv[N*5];
void dfs1(int x)
{
sz[x]=1;
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(de[y]) continue;
vv[i>>1]=1;
fa[y]=x,de[y]=de[x]+1,dfs1(y);
sz[x]+=sz[y],hs[x]=sz[hs[x]]>sz[y]?hs[x]:y;
}
}
void dfs2(int x)
{
if(hs[x]) top[hs[x]]=top[x],dfs2(hs[x]);
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(!vv[i>>1]||y==fa[x]||y==hs[x]) continue;
top[y]=y,dfs2(y);
}
}
int glca(int x,int y)
{
while(top[x]!=top[y])
{
if(de[top[x]]<de[top[y]]) swap(x,y);
x=fa[top[x]];
}
return de[x]<de[y]?x:y;
}
void dfs3(int x)
{
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(!vv[i>>1]||y==fa[x]) continue;
dfs3(y),a[x]^=a[y],w[i>>1]=a[y];
}
}
int main()
{
n=rd(),m=rd();
for(int i=1;i<=m;++i) add(rd(),rd());
de[1]=1,dfs1(1);
top[1]=1,dfs2(1);
for(int i=1;i<=m;++i)
if(!vv[i])
{
w[i]=(1ull*rand()<<32)|1ull*rand();
int x=to[i<<1],y=to[i<<1|1],lca=glca(x,y);
if(y==lca) swap(x,y);
a[x]^=w[i],a[y]^=w[i];
if(x!=lca) a[lca]^=w[i];
}
dfs3(1);
q=rd();
int las=0;
while(q--)
{
memset(bs,0,sizeof(bs));
bool ok=0;
int kk=rd();
while(kk--)
{
uLL x=w[rd()^las];
for(int i=64;~i;--i)
if(x>>i&1)
{
if(!bs[i]){bs[i]=x;break;}
x^=bs[i];
if(!x) break;
}
ok|=!x;
}
las+=!ok;
puts(ok?"Disconnected":"Connected");
}
return 0;
}