题解:为每条非树边赋一个权值
每条树边的权值为覆盖他的非树边权值异或和
如果边集的子集线性相关,相当于把树边和非树边拦腰砍断,则不连通
用线性基判断线性相关
问题:为什么srand(time(0))会RE?
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
using namespace std;
const int maxn=1000009;
int n,m,T;
int rx[maxn],ry[maxn],vis[maxn],rd[maxn];
int ufsfa[maxn];
int Getf(int x){
if(ufsfa[x]==x)return x;
return ufsfa[x]=Getf(ufsfa[x]);
}
void Unionn(int x,int y){
int fx=Getf(x);
int fy=Getf(y);
if(fx!=fy)ufsfa[fx]=fy;
}
int cntedge;
int head[maxn];
int to[maxn],nex[maxn],num[maxn];
void Addedge(int x,int y,int ide){
nex[++cntedge]=head[x];
to[cntedge]=y;
num[cntedge]=ide;
head[x]=cntedge;
}
int father[maxn];
int dep[maxn];
int fatheredge[maxn];
int Dfs(int now,int fa){
father[now]=fa;
dep[now]=dep[fa]+1;
for(int i=head[now];i;i=nex[i]){
if(to[i]==fa)continue;
fatheredge[to[i]]=num[i];
Dfs(to[i],now);
}
}
int mar[maxn];
void Dp(int x,int fa){
for(int i=head[x];i;i=nex[i]){
if(to[i]==fa)continue;
Dp(to[i],x);
mar[x]^=mar[to[i]];
}
}
int lastans;
int a[maxn];
int c[100];
int isOK(int n){
memset(c,0,sizeof(c));
for(int i=1;i<=n;++i){
int x=rd[a[i]];
for(int j=30;j>=1;--j){
if(x&(1<<(j-1))){
if(c[j]==0){
c[j]=x;
break;
}else{
x^=c[j];
}
}
}
if(x==0)return 0;
}
// for(int i=30;i>=1;--i)printf("%d ",c[i]);
// cout<<endl;
return 1;
}
void Minit(){
lastans=0;
memset(mar,0,sizeof(mar));
dep[0]=0;
memset(head,0,sizeof(head));
memset(vis,0,sizeof(vis));
cntedge=0;
}
int main(){
// int fuck=time(0);
srand(19260917);
scanf("%d%d",&n,&m);
Minit();
for(int i=1;i<=n;++i)ufsfa[i]=i;
for(int i=1;i<=m;++i){
scanf("%d%d",&rx[i],&ry[i]);
if(Getf(rx[i])!=Getf(ry[i])){
Unionn(rx[i],ry[i]);
vis[i]=1;
Addedge(rx[i],ry[i],i);
Addedge(ry[i],rx[i],i);
}
}
Dfs(1,0);
for(int i=1;i<=m;++i){
if(vis[i])continue;
if(dep[rx[i]]>dep[ry[i]])swap(rx[i],ry[i]);
int dist=(int)(1LL*rand()*rand()%1000000000+1);
// cout<<dist<<endl;
rd[i]=dist;
mar[ry[i]]^=dist;
mar[rx[i]]^=dist;
}
Dp(1,0);
for(int i=2;i<=n;++i){
rd[fatheredge[i]]=mar[i];
}
// for(int i=1;i<=m;++i)printf("%d ",rd[i]);
// cout<<endl;
scanf("%d",&T);
while(T--){
int k;
scanf("%d",&k);k^=lastans;
for(int i=1;i<=k;++i)scanf("%d",&a[i]);
for(int i=1;i<=k;++i)a[i]^=lastans;
if(isOK(k))++lastans,printf("Connected\n");
else printf("Disconnected\n");
}
return 0;
}