【题目分析】
腊鸡题目卡题面。
大概的意思就是给一张无向图,每次删掉其中一些边,问是否联通。
首先想到的是Bitset,可以做到n^2/64。显然过不了。
然而这是lyd在给我们讲线性基的时候的一道题目。↓
首先构建dfs树。
发现图不联通的时候,当且仅当删去了树边和所有覆盖它的非树边。
所以对于每一条非树边随机一个权值,然后每条树边为所有覆盖它的非树边的权值的异或。
每次判断是否线性无关即可。
神题!
【代码】
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <set> #include <map> #include <string> #include <algorithm> #include <vector> #include <iostream> #include <queue> using namespace std; #define maxn 100005 #define maxm 1000005 #define mxle 65 #define ll long long #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define inf (0x3f3f3f3f) void Finout() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif } int Getint() { int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } vector <int> v[maxn]; int h[maxm],fr[maxm],to[maxm],ne[maxm],en=0,f[maxn],tag[maxm]; int w[maxm],b[maxm]; int vis[maxm]; void add(int a,int b) { fr[en]=a; to[en]=b; ne[en]=h[a]; h[a]=en++; fr[en]=b; to[en]=a; ne[en]=h[b]; h[b]=en++; } void dfs1(int o,int fa) { vis[o]=1; for (int i=h[o];i>=0;i=ne[i]) { if (!vis[to[i]]) dfs1(to[i],o); else if (!w[i]&&to[i]!=fa) { w[i]=w[i^1]=rand()*711; b[o]^=w[i]; b[to[i]]^=w[i]; } } } int n,m; void dfs2(int o) { vis[o]=1; for (int i=h[o];i>=0;i=ne[i]) { if (!vis[to[i]]) { dfs2(to[i]); w[i]=w[i^1]=b[to[i]]; b[o]^=b[to[i]]; } } } struct Base{ int lb[mxle]; bool add(int x) { D(i,30,0) { if ((x>>i)&1) { if (!lb[i]) {lb[i]=x;return false;} else x^=lb[i]; } } return true; } void init(int x){memset(lb,0,sizeof lb);add(x);} }bas; int q,x,y; int main() { memset(h,-1,sizeof h); srand(20000416); Finout(); n=Getint();m=Getint(); F(i,1,m) add(Getint(),Getint()); dfs1(1,0); memset(vis,0,sizeof vis); dfs2(1); int ans=0,flag=0; q=Getint(); F(i,1,q) { flag=0; x=Getint(); bas.init(0); F(i,1,x) { y=Getint(); y^=ans; if (bas.add(w[2*y-1])) flag=1; } flag^=1; if (flag) printf("Connected "); else printf("Disconnected "); ans+=flag; } }