BZOJ 3563 DZY Loves Chinese
题解:为每条非树边赋一个权值
每条树边的权值为覆盖他的非树边权值异或和
如果边集的子集线性相关,相当于把树边和非树边拦腰砍断,则不连通
用线性基判断线性相关
问题:为什么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; }
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!