BZOJ3569 DZY-Loves-Chinese-II

版权声明:随意转载,愿意的话提一句作者就好了 https://blog.csdn.net/stone41123/article/details/84061085

Link

Difficulty

算法难度5,思维难度7,代码难度5

Description

给定一个无向图, n n 个点, m m 条边, q q 组询问

每组询问删除 k k 条边,问整张图是否连通

强制在线

n 1 0 5 , m 5 × 1 0 5 , q 5 × 1 0 4 n\le 10^5,m\le 5\times 10^5,q\le 5\times 10^4

Solution

发现在 k k 条删掉的边中,只要删掉其中一些边就可以断开这张图,其他边无关紧要

以下就开始神仙了

我们随便取这张图的一棵生成树(dfs树就可以的)

然后给非树边随机一个非负权值,树边的权值就等于所有跨越它的非树边的权值异或和

如果有一组边可以断开这张图,那么一定存在一种方案使得:

从它们之中取一些边,异或起来恰好为0(这些边就是我说的那些必要的边)

所以我们要判断是否存在一种方案使得这些边的异或和为0

这东西有个题是 k 4 k\le 4 来着,可以暴力枚举,但这个题不行了

我们可以使用线性基来判断

每次插入之后判断剩下的那个数是否等于0,如果等于0就说明不连通了

时间复杂度 O ( n + m + q l o g V ) O(n+m+qlogV)

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<ctime>
#define LL long long
using namespace std;
inline int read(){
    int x=0,f=1;char ch=' ';
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return f==1?x:-x;
}
const int N=1e5+5,M=1e6+5;
inline double Rand(){
	return (double)rand()/(double)RAND_MAX;
}
int n,m,q,tot;
int head[N],to[M],Next[M],val[M],is[M];
inline void addedge(int x,int y,int c){
	to[++tot]=y;
	Next[tot]=head[x];
	head[x]=tot;
	val[tot]=c;
}
int X[M],Y[M],V[M];
int vis[N],dfn[N],dfn_clock,ed[N];
inline void dfs(int x,int fa){
	vis[x]=1;
	dfn[x]=++dfn_clock;
	for(int i=head[x];i;i=Next[i]){
		int u=to[i];
		if(u==fa || vis[u])continue;
		is[i]=1;
		dfs(u,x);
	}
	ed[x]=dfn_clock;
}
int t[N];
inline void dfs2(int x,int fa){
	vis[x]=1;
	for(int i=head[x];i;i=Next[i]){
		int u=to[i];
		if(u==fa || vis[u])continue;
		dfs2(u,x);
		t[x]^=t[u];
		val[i]=t[u];
		if(i&1)val[i+1]=t[u];
		else val[i-1]=t[u];
	}
}
int b[32];
int main(){
	srand(time(0));
	n=read();m=read();
	for(int i=1;i<=m;++i){
		int x=read(),y=read(),c=Rand()*1e9+1;
		addedge(x,y,c);addedge(y,x,c);
		X[i]=x;Y[i]=y;V[i]=c;
	}
	dfs(1,0);
	for(int i=1;i<=m;++i){
		if(is[2*i] || is[2*i-1])continue;
	    t[X[i]]^=V[i];
		t[Y[i]]^=V[i];
	}
	for(int i=1;i<=n;++i)vis[i]=0;
	dfs2(1,0);
	int ans=0;
	q=read();
	for(int s=1;s<=q;++s){
		int k=read(),flag=1;
		for(int i=0;i<=31;++i)b[i]=0;
		while(k--){
			int x=read()^ans;
			x=val[x*2];
			for(int i=31;i>=0;--i){
				if((x>>i)&1){
					if(!b[i]){b[i]=x;break;}
					x^=b[i];
				}
			}
			if(!x)flag=0;
		}
		if(flag){printf("Connected\n");ans++;}
		else printf("Disconnected\n");
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/stone41123/article/details/84061085
今日推荐