• bzoj 3569 DZY Loves Chinese II


    bzoj

    对于这题先套路的找出一棵生成树,然后还会剩下一些非树边,要删边使得图不连通(假设先删非树边)当且仅当删掉了一条没有返祖边覆盖的树边,或者是删了两条被相同的非树边集合覆盖的树边

    现在要处理这个问题.我们给所有非树边一个随机权值,然后树边的权值就是覆盖它的非树边权值异或和,这个可以树上差分实现,那么两条树边如果异或和相等就认为覆盖它们的非树边集合相同,如果一条树边异或和为0就认为没有被覆盖.如果我们的随机的值域为(2^w),那么出错的概率就是(frac{1}{2^w}),因为某个数只有正好等于那个对应的数才会出错

    先给结论.对于给出的一个边集,删掉以后不连通,当且仅当这个边集中有一个子集权值异或和为0.接下来是感性证明:如果这个子集全是非树边那应该就在别的地方直接WA了;如果有一个树边,也就是选出来的其他非树边都是覆盖它的,所以删掉后会不连通;如果有(ge 2)个树边,那么一定可以把其他一些其他非树边分别异或到树边上去,使得有两个树边异或和相同.顺便再推荐一波理性证明.所以实现可以用线性基,做到出现线性相关的子集就可以不连通

    #include<bits/stdc++.h>
    #define LL long long
    #define uLL unsigned long long
    #define db double
    
    using namespace std;
    const int N=1e5+10;
    int rd()
    {
    	int x=0,w=1;char ch=0;
    	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    	return x*w;
    }
    int to[N*10],nt[N*10],hd[N],tot=1;
    void add(int x,int y)
    {
    	++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
    	++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
    }
    int n,m,q,fa[N],de[N],sz[N],hs[N],top[N];
    uLL a[N],w[N*5],bs[70];
    bool vv[N*5];
    void dfs1(int x)
    {
    	sz[x]=1;
    	for(int i=hd[x];i;i=nt[i])
    	{
    		int y=to[i];
    		if(de[y]) continue;
    		vv[i>>1]=1;
    		fa[y]=x,de[y]=de[x]+1,dfs1(y);
    		sz[x]+=sz[y],hs[x]=sz[hs[x]]>sz[y]?hs[x]:y;
    	}
    }
    void dfs2(int x)
    {
    	if(hs[x]) top[hs[x]]=top[x],dfs2(hs[x]);
    	for(int i=hd[x];i;i=nt[i])
    	{
    		int y=to[i];
    		if(!vv[i>>1]||y==fa[x]||y==hs[x]) continue;
    		top[y]=y,dfs2(y);
    	}
    }
    int glca(int x,int y)
    {
    	while(top[x]!=top[y])
    	{
    		if(de[top[x]]<de[top[y]]) swap(x,y);
    		x=fa[top[x]];
    	}
    	return de[x]<de[y]?x:y;
    }
    void dfs3(int x)
    {
    	for(int i=hd[x];i;i=nt[i])
    	{
    		int y=to[i];
    		if(!vv[i>>1]||y==fa[x]) continue;
    		dfs3(y),a[x]^=a[y],w[i>>1]=a[y];
    	}
    }
    
    int main()
    {
    	n=rd(),m=rd();
    	for(int i=1;i<=m;++i) add(rd(),rd());
    	de[1]=1,dfs1(1);
    	top[1]=1,dfs2(1);
    	for(int i=1;i<=m;++i)
    		if(!vv[i])
    		{
    			w[i]=(1ull*rand()<<32)|1ull*rand();
    			int x=to[i<<1],y=to[i<<1|1],lca=glca(x,y);
    			if(y==lca) swap(x,y);
    			a[x]^=w[i],a[y]^=w[i];
    			if(x!=lca) a[lca]^=w[i];
    		}
    	dfs3(1);
    	q=rd();
    	int las=0;
    	while(q--)
    	{
    		memset(bs,0,sizeof(bs));
    		bool ok=0;
    		int kk=rd();
    		while(kk--)
    		{
    			uLL x=w[rd()^las];
    			for(int i=64;~i;--i)
    				if(x>>i&1)
    				{
    					if(!bs[i]){bs[i]=x;break;}
    					x^=bs[i];
    					if(!x) break;
    				}
    			ok|=!x;
    		}
    		las+=!ok;
    		puts(ok?"Disconnected":"Connected");
    	}
        return 0;
    }
    
  • 相关阅读:
    [原创]mac终端前面的计算机名怎么改??
    iOS获取当前设备方向
    mac电脑Coding显示/隐藏文件
    从tomcat7升级到tomcat8的一个坑
    Tomcat环境开发技巧
    No.2 网络功能
    No.1 持久化
    No.0 项目起步
    读mysqlbinlog二三事
    版本号小常识
  • 原文地址:https://www.cnblogs.com/smyjr/p/11614760.html
Copyright © 2020-2023  润新知