http://www.lydsy.com/JudgeOnline/problem.php?id=3569
先dfs出一棵搜索树,对于非树边给它rand一个边权,然后对于树边的边权等于它被覆盖的非树边的异或和
对于删去的k边,若存在非空子集的异或和为0,说明图不连通,这个可以线性基搞搞
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
using namespace std;
const int N=500011;
int nxt[N],las[N],to[N],w[N],_w[N];
bool vis[N];
int a[31];
int tot,n,m,q,k,ans,x,y;
inline void add(int x,int y){
nxt[++tot]=las[x];las[x]=tot;to[tot]=y;
}
inline void dfs1(int now){
vis[now]=1;
for(register int e=las[now];e;e=nxt[e])
if(!vis[to[e]])
dfs1(to[e]);
else{
w[e]=rand();
_w[to[e]]^=w[e];
_w[now]^=w[e];
}
}
inline void dfs2(int now){
vis[now]=1;
for(register int e=las[now];e;e=nxt[e])
if(!vis[to[e]]){
dfs2(to[e]);
w[e]^=_w[to[e]];
_w[now]^=_w[to[e]];
}
}
inline bool check(){
register int now=0;
for(register int i=30;~i;--i){
for(register int j=now+1;j<=k;++j)
if(a[j]&(1<<i)){
swap(a[j],a[++now]);
for(register int l=1;l<=k;++l)
if(l!=now&&(a[l]&(1<<i)))
a[l]^=a[now];
break;
}
}
return a[k]?0:1;
}
int main(){
srand(20011214);
scanf("%d%d",&n,&m);
FOR(i,1,m){
scanf("%d%d",&x,&y);
if(x>y)swap(x,y);
add(x,y);
}
dfs1(1);
FOR(i,1,n)
vis[i]=0;
dfs2(1);
scanf("%d",&q);
while(q--){
scanf("%d",&k);
FOR(i,1,k){
scanf("%d",&x);
x^=ans;a[i]=w[x];
}
if(check())
puts("Disconnected");
else{
puts("Connected");
++ans;
}
}
return 0;
}