zoukankan      html  css  js  c++  java
  • luoguP5227 [AHOI2013]连通图(线性基做法)

    题意

    神仙哈希做法。

    随便找个生成树,给每个非树边赋一个值,树边的值为所有覆盖它的边的值得异或和。

    删去边集使得图不联通当且即当边集存在一个子集异或和为0,可以用线性基。

    证明的话好像画个图挺显然的

    upd:

    找到了一份详细的证明
    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+10;
    const int maxm=2*1e5+10;
    const int maxQ=1e5+10;
    int n,m,Q,cnt;
    int head[maxn],fa[maxn],sum[maxn],val[maxm],xord[40];
    bool check[maxm];
    struct Edge{int u,v;}E[maxm];
    struct edge{int to,nxt,id;}e[maxn<<1];
    vector<int>edge[maxQ];
    inline int read()
    {
    	char c=getchar();int res=0,f=1;
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    	return res*f;
    }
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    inline void add(int u,int v,int id)
    {
    	e[++cnt].nxt=head[u];
    	head[u]=cnt;
    	e[cnt].to=v;
    	e[cnt].id=id;
    }
    void dfs(int x,int pre)
    {
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(y==pre)continue;
    		dfs(y,x);sum[x]^=sum[y];val[e[i].id]=sum[y];
    	}
    }
    inline bool insert(int x)
    {
    	for(int i=31;~i;i--)
    	{
    		if(!(x&(1<<i)))continue;
    		if(!xord[i]){xord[i]=x;return 1;}
    		else x^=xord[i];
    	}
    	return 0;
    }
    int main()
    {
    	srand(time(0));
    	n=read(),m=read();
    	for(int i=1;i<=m;i++)E[i].u=read(),E[i].v=read(),val[i]=rand();
    	Q=read();
    	for(int i=1;i<=Q;i++)
    	{
    		int k=read(),id;
    		while(k--)id=read(),edge[i].push_back(id);
    	}
    	for(int i=1;i<=n;i++)fa[i]=i;
    	for(int i=1;i<=m;i++)
    	{
    		int x=find(E[i].u),y=find(E[i].v);
    		if(x==y)
    		{
    			sum[E[i].u]^=val[i];sum[E[i].v]^=val[i];
    			continue;
    		}
    		fa[x]=y;check[i]=1;
    		add(E[i].u,E[i].v,i);add(E[i].v,E[i].u,i);
    	}
    	dfs(1,0);
    	for(int i=1;i<=Q;i++)
    	{
    		memset(xord,0,sizeof(xord));
    		bool flag=1;
    		for(unsigned int j=0;j<edge[i].size();j++)if(!insert(val[edge[i][j]])){flag=0;break;}
    		if(flag)puts("Connected");
    		else puts("Disconnected");
    	}
    	return 0;
    }
    
  • 相关阅读:
    解决MAMP启动mysql服务 但是Navicat连接不上
    iOS 更改状态栏颜色和隐藏状态栏
    Xcode 常用代码段
    iOS开发小技巧
    怎么让self.view的Y从navigationBar下面开始计算
    iOS强制横屏或强制竖屏
    判断当前viewcontroller是push还是present的方式显示的
    Git命令速查表
    全栈程序员的新玩具Rust(一) IDE环境
    火狐的野望
  • 原文地址:https://www.cnblogs.com/nofind/p/12025170.html
Copyright © 2011-2022 走看看