1. 程式人生 > >BZOJ3569: DZY Loves Chinese II(BZOJ3563)

BZOJ3569: DZY Loves Chinese II(BZOJ3563)

線性基

(3563是搞笑的。。。因為K也被異或,我們就可以倒推出其他答案,只要做最後一次就行了)

線性基神題

我們對原圖建DFS樹,這樣非樹邊就只有返祖邊了。我們給每條非樹邊隨機一個權值,樹邊的權值為覆蓋它的非樹邊權值的異或和。這樣當刪除的邊中有異或和為0的子集時就是不連通的,這個用線性基判斷。

程式碼:

#include<cctype>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define N 100005
#define M 500005
#define
F inline
using namespace std; struct edge{ int nxt,to,id; }ed[M<<1]; int n,m,k,sum,ti,h[N],p[40],a[N],b[M]; bool f[N]; F char readc(){ static char buf[100000],*l=buf,*r=buf; if (l==r) r=(l=buf)+fread(buf,1,100000,stdin); return l==r?EOF:*l++; } F int _read(){ int x=0; char ch=readc(); while (!isdigit
(ch)) ch=readc(); while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc(); return x; } #define add(x,y,z) ed[++k]=(edge){h[x],y,z},h[x]=k void dfs(int x,int fa){ f[x]=true; for (int i=h[x],v,p;i;i=ed[i].nxt) if ((v=ed[i].to)!=fa) if (f[v=ed[i].to]){ if (!b[ed[i].id]) b[ed[
i].id]=p=rand(),a[x]^=p,a[v]^=p; } else dfs(v,x),b[ed[i].id]=a[v],a[x]^=a[v]; } F bool pd(int x){ for (int i=30;~i;i--) if (x&(1<<i)) if (!p[i]) return p[i]=x,true; else x^=p[i]; return x; } int main(){ srand(19260817); n=_read(),m=_read(); for (int i=1,x,y;i<=m;i++) x=_read(),y=_read(),add(x,y,i),add(y,x,i); dfs(1,0); for (int t=_read();t;t--){ int k=_read(); bool f=true; memset(p,0,sizeof(p)); for (int i=1,x;i<=k;i++) if (!pd(b[_read()^sum])) f=false; sum+=f,puts(f?"Connected":"Disconnected"); } return 0; }