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

  

 

posted @ 2018-02-19 21:00  ws_zzy  阅读(135)  评论(0编辑  收藏  举报