DZY Loves Chinese II
给一张无向图,每次删掉一些边(非永久操作),问图是否连通。
N≤100000 M≤500000 Q≤50000 1≤K≤15
数据保证没有重边与自环
题解
取一个生成树,对每条非树边取一个随机权值,对每条树边设为“覆盖它的所有非树边”的权值的xor,这个可以用类似树上差分的方式实现。
对于每次询问,只要某个子集的所有边xor值是0,那么就不连通,否则连通。
判断用线性基就好了。时间复杂度\(O(n+\Sigma k \times 64)\)。
#include<bits/stdc++.h>
#define co const
#define il inline
template<class T> T read(){
T x=0,w=1;char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*w;
}
template<class T> T read(T&x){
return x=read<T>();
}
using namespace std;
typedef long long LL;
il LL van(){
return rand()|rand()<<15|(LL)rand()<<30|(LL)rand()<<45|(LL)rand()<<60;
}
co int N=100000+10;
int n,m;
struct edge{int y,next;}pool[10*N];
int head[N],tot;
il void add_edge(int x,int y){
pool[++tot]=(edge){y,head[x]},head[x]=tot;
}
int dep[N],adj[N];
LL dif[N],val[5*N];
void dfs(int x,int fa){
for(int i=head[x];i;i=pool[i].next){
int y=pool[i].y;
if(y==fa) continue;
if(!dep[y]){
dep[y]=dep[x]+1,adj[y]=(i+1)>>1;
dfs(y,x),
dif[x]^=dif[y];
}
else if(dep[y]<dep[x]){
int id=(i+1)>>1;
val[id]=van();
dif[x]^=val[id],dif[y]^=val[id];
}
}
val[adj[x]]=dif[x];
}
LL bas[64];
bool insert(LL v){
for(int i=63;v&&i>=0;--i)if(v>>i&1){
if(!bas[i]) return bas[i]=v,1;
else v^=bas[i];
}
return 0;
}
int main(){
srand(20030506);
read(n),read(m);
for(int i=1;i<=m;++i){
int x=read<int>(),y=read<int>();
add_edge(x,y),add_edge(y,x);
}
dfs(1,0);
int ans=0;
for(int q=read<int>();q--;){
int k=read<int>();
bool valid=1;
memset(bas,0,sizeof bas);
for(int i=1;i<=k;++i)
if(!insert(val[read<int>()^ans])) valid=0;
ans+=valid,puts(valid?"Connected":"Disconnected");
}
return 0;
}