BZOJ3569 DZY-Loves-Chinese-II
阿新 • • 發佈:2018-11-14
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;
}