Link
随便找一个ST,对每条非树边rand一个([0,2^{omega}))的权值,再令每条树边的权值为所有覆盖它的非树边权值的异或和,这样图不连通当且仅当删掉的边权线性相关。
检查是否线性相关可以利用线性基。
这个算法的正确性大概是((1-frac1{2^{omega}})^{2^k})。
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
const int N=100007,M=1000007;
int n,m,t,tot=1,head[N],ver[M],Next[M],w[M>>1],val[N],id[N],base[32];
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
void add(int u,int v){ver[++tot]=v,Next[tot]=head[u],head[u]=tot;}
void dfs(int u,int fa)
{
id[u]=++t;
for(int i=head[u],v;i;i=Next[i])
if((v=ver[i])^fa)
{
if(!id[v]) dfs(v,u),val[u]^=val[v],w[i>>1]=val[v];
else if(id[v]<id[u]) w[i>>1]=rand(),val[u]^=w[i>>1],val[v]^=w[i>>1];
}
}
int main()
{
n=read(),m=read(),srand(19260817);
for(int i=1,u,v;i<=m;++i) u=read(),v=read(),add(u,v),add(v,u);
dfs(1,0);
for(int q=read(),ans=0;q;--q)
{
memset(base,0,128);int k,f=1;
for(k=read();k;--k)
{
int x=w[read()^ans],F=0;
if(!f) continue;
for(int i=30;~i;--i)
if(x>>i&1)
{
if(base[i]) x^=base[i];
else {base[i]=x,F=1;break;}
}
f&=F;
}
puts(f? "Connected":"Disconnected"),ans+=f;
}
}