版权声明:随意转载,愿意的话提一句作者就好了 https://blog.csdn.net/stone41123/article/details/84061085
Link
Difficulty
算法难度5,思维难度7,代码难度5
Description
给定一个无向图, 个点, 条边, 组询问
每组询问删除 条边,问整张图是否连通
强制在线
Solution
发现在 条删掉的边中,只要删掉其中一些边就可以断开这张图,其他边无关紧要
以下就开始神仙了
我们随便取这张图的一棵生成树(dfs树就可以的)
然后给非树边随机一个非负权值,树边的权值就等于所有跨越它的非树边的权值异或和
如果有一组边可以断开这张图,那么一定存在一种方案使得:
从它们之中取一些边,异或起来恰好为0(这些边就是我说的那些必要的边)
所以我们要判断是否存在一种方案使得这些边的异或和为0
这东西有个题是 来着,可以暴力枚举,但这个题不行了
我们可以使用线性基来判断
每次插入之后判断剩下的那个数是否等于0,如果等于0就说明不连通了
时间复杂度
#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;
}