BZOJ3569
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; }