题解 P5227 【[AHOI2013]连通图】
神仙哈希题,复杂度
前置定义:非树边的覆盖树边指的是非树边的两个端点在树上的最短路覆盖的边。记 xor 为
考虑给非树边一个随机权值,而树边的权值为所有覆盖其的非树边的
证明:考虑被分开的两个极大连通点集之间被删掉的边的
当
显然这些边至少有一条树边,设深度最小的那条为
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
typedef unsigned long long ll;
const int N=1e5+2,M=2e5+2;
ll v[N],val[M],js;
int lj[M],nxt[M],bh[M],fir[N],f[N];
int n,m,i,x,y,z,c,bs;
inline void read(int &x)
{
c=getchar();
while ((c<48)||(c>57)) c=getchar();
x=c^48;c=getchar();
while ((c>=48)&&(c<=57))
{
x=x*10+(c^48);
c=getchar();
}
}
int getf(int x)
{
if (f[x]==x) return x;
return f[x]=getf(f[x]);
}
inline ll sj()
{
js=rand();js<<=31;return js|rand();
}
inline void add(int x,int y,int z)
{
lj[++bs]=y;
bh[bs]=z;
nxt[bs]=fir[x];
fir[x]=bs;
lj[++bs]=x;
bh[bs]=z;
nxt[bs]=fir[y];
fir[y]=bs;
}
void dfs(int x)
{
int i;
for (i=fir[x];i;i=nxt[i]) if (lj[i]!=f[x])
{
f[lj[i]]=x;
dfs(lj[i]);
v[x]^=(val[bh[i]]=v[lj[i]]);
}
}
int main()
{
srand(383778817);
read(n);read(m);
for (i=1;i<=n;i++) f[i]=i;
for (i=1;i<=m;i++)
{
read(x);read(y);
if (getf(x)==getf(y)) {v[x]^=(val[i]=sj());v[y]^=val[i];}
else {add(x,y,i);f[f[x]]=f[y];}
}memset(f,0,sizeof(f));dfs(1);read(m);
while (m--)
{
read(x);
if (x==1) {read(y);if (val[y]) puts("Connected"); else puts("Disconnected");}
else if (x==2) {read(y);read(z);if ((val[y])&&(val[y]^val[z])&&(val[z])) puts("Connected"); else puts("Disconnected");}
else if (x==3) {read(y);read(z);read(i);if ((val[y])&&(val[z])&&(val[i])&&(val[y]^val[z])&&(val[z]^val[i])&&(val[y]^val[i])&&(val[y]^val[z]^val[i])) puts("Connected"); else puts("Disconnected");}
else {read(x);read(y);read(z);read(i);if ((val[x])&&(val[y])&&(val[z])&&(val[i])&&(val[x]^val[y])&&(val[x]^val[z])&&(val[x]^val[i])&&(val[z]^val[y])&&(val[i]^val[y])&&(val[z]^val[i])&&(val[x]^val[y]^val[z])&&(val[x]^val[y]^val[i])&&(val[x]^val[i]^val[z])&&(val[i]^val[y]^val[z])&&(val[x]^val[y]^val[z]^val[i])) puts("Connected"); else puts("Disconnected");}
}
}