其他分享
首页 > 其他分享> > DZY Loves Chinese II

DZY Loves Chinese II

作者:互联网

一、题目

点此看题

二、解法

建立原图的 \(\tt dfs\) 树,分树边和非树边考察连通性。设删边集合是 \(P\),设覆盖树边 \(e\) 的非树边构成集合 \(S_e\),特别地,对于非树边 \(e\) 令 \(S_e=\{e\}\),有结论:

必要性:对于一个极小的割边集合 \(Q\) 证明 \(\Delta _{e\in Q} S_e=\varnothing\) 即可。由于 \(Q\) 是割且 \(Q\) 极小,那么删去 \(Q\) 后图一定被分为两个联通块,对于与根不再联通的连通块,把它缩成一个点来考虑:

其中 \(3\) 是与根不再联通的连通块,那么对于 \(3\) 子树内未被删除的非树边,一定连向了 \(3\) 的一个严格祖先。那么它恰好经过了两条割边,被异或上了两次所以贡献为 \(0\);对于 \(3\) 子树内被删除了的树边,一定恰好经过一条割边,由于其自身需要贡献一次,所以贡献也为 \(0\)

充分性:对于满足 \(\Delta_{e\in Q} S_e=\varnothing\) 的集合 \(Q\) 证明它是割即可。至少会有一条树边 \(e_0\in Q\),那么被删除的树边会把原树划分为若干个连通块,我们把每个连通块缩成一个点,再用这些被删除的树边重构。考虑加入未被删除的非树边,如果把树黑白染色,那么这些非树边只会连接同色点,最后黑点和白点之间一定不连通,所以 \(Q\) 是割。

知道这个结论后,给每条非树边赋一个随机权值,对每条树边求出对应的权值,然后用线性基就可以判断这个条件了,时间复杂度 \(O(m+kq\log V)\)

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
using namespace std;
const int M = 1000005;
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,m,tot=1,Ind,f[M],w[M],a[M],b[32],id[M];
struct edge{int v,next;}e[M];
void dfs(int u,int fa)
{
	id[u]=++Ind;
	for(int i=f[u];i;i=e[i].next)
	{
		int v=e[i].v;
		if(v==fa) continue;
		if(!id[v])
			dfs(v,u),a[u]^=a[v],w[i>>1]=a[v];
		else if(id[u]>id[v])
			w[i>>1]=rand(),a[u]^=w[i>>1],a[v]^=w[i>>1];
	}
}
int main()
{
	n=read();m=read();srand(19260817);
	for(int i=1;i<=m;i++)
	{
		int u=read(),v=read();
		e[++tot]=edge{v,f[u]},f[u]=tot;
		e[++tot]=edge{u,f[v]},f[v]=tot;
	}
	dfs(1,0);
	for(int t=0,q=read();q--;)
	{
		int k=read(),f=1;
		memset(b,0,sizeof b);
		while(k--)
		{
			int z=read()^t,x=w[z],F=0;
			if(!f) continue;
			for(int i=30;i>=0;i--) if(x>>i&1)
			{
				if(b[i]) x^=b[i];
				else {b[i]=x;F=1;break;}
			}
			f&=F;
		}
		t+=f;
		puts(f?"Connected":"Disconnected");
	}
}

标签:连通,include,Chinese,int,II,树边,Delta,DZY,非树边
来源: https://www.cnblogs.com/C202044zxy/p/16472585.html