BZOJ3569 DZY Loves Chinese II

Link
随便找一个ST,对每条非树边rand一个\([0,2^{\omega})\)的权值,再令每条树边的权值为所有覆盖它的非树边权值的异或和,这样图不连通当且仅当删掉的边权线性相关。
检查是否线性相关可以利用线性基。
这个算法的正确性大概是\((1-\frac1{2^{\omega}})^{2^k}\)

#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
const int N=100007,M=1000007;
int n,m,t,tot=1,head[N],ver[M],Next[M],w[M>>1],val[N],id[N],base[32];
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
void add(int u,int v){ver[++tot]=v,Next[tot]=head[u],head[u]=tot;}
void dfs(int u,int fa)
{
    id[u]=++t;
    for(int i=head[u],v;i;i=Next[i])
	if((v=ver[i])^fa)
	{
	    if(!id[v]) dfs(v,u),val[u]^=val[v],w[i>>1]=val[v];
	    else if(id[v]<id[u])  w[i>>1]=rand(),val[u]^=w[i>>1],val[v]^=w[i>>1];
	}
}
int main()
{
    n=read(),m=read(),srand(19260817);
    for(int i=1,u,v;i<=m;++i) u=read(),v=read(),add(u,v),add(v,u);
    dfs(1,0);
    for(int q=read(),ans=0;q;--q)
    {
	memset(base,0,128);int k,f=1;
	for(k=read();k;--k)
	{
	    int x=w[read()^ans],F=0;
	    if(!f) continue;
	    for(int i=30;~i;--i)
		if(x>>i&1)
		{
		    if(base[i]) x^=base[i];
		    else {base[i]=x,F=1;break;}
		}
	    f&=F;
	}
	puts(f? "Connected":"Disconnected"),ans+=f;
    }
}
posted @ 2020-01-22 17:39  Shiina_Mashiro  阅读(89)  评论(0编辑  收藏  举报