BZOJ4998 星球联盟(LCT+双连通分量+并查集)
即要求动态维护边双。出现环时将路径上的点合并即可。LCT维护。具体地,加边成环时makeroot+access+splay一套把这段路径提出来,暴力dfs修改并查集祖先,并将这部分与根断开,视为删除这些点,以后就以并查集中的祖先代替这些点。access时更新每个点的父亲。注意由于之前的删点操作,判断是否连通需要另开一个并查集而不能findroot。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 200010 #define lson tree[k].ch[0] #define rson tree[k].ch[1] #define lself tree[tree[k].fa].ch[0] #define rself tree[tree[k].fa].ch[1] char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,q,fa[N],fa2[N],size[N]; struct data{int ch[2],fa,rev; }tree[N]; int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} int find2(int x){return fa2[x]==x?x:fa2[x]=find2(fa2[x]);} void rev(int k){if (k) swap(lson,rson),tree[k].rev^=1;} void down(int k){if (tree[k].rev) rev(lson),rev(rson),tree[k].rev=0;} int whichson(int k){return rself==k;} bool isroot(int k){return lself!=k&&rself!=k;} void push(int k){if (!isroot(k)) push(tree[k].fa);down(k);} void move(int k) { int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k); if (!isroot(fa)) tree[gf].ch[whichson(fa)]=k;tree[k].fa=gf; tree[fa].ch[p]=tree[k].ch[!p],tree[tree[k].ch[!p]].fa=fa; tree[k].ch[!p]=fa,tree[fa].fa=k; } void splay(int k) { push(k); while (!isroot(k)) { int fa=tree[k].fa; if (!isroot(fa)) if (whichson(fa)^whichson(k)) move(k); else move(fa); move(k); } } void access(int k){for (int t=0;k;t=k,k=tree[k].fa=find(tree[k].fa)) splay(k),tree[k].ch[1]=t;} void makeroot(int k){access(k),splay(k),rev(k);} void link(int x,int y){makeroot(x),tree[x].fa=y,fa2[find2(x)]=find2(y);} void dfs(int k,int x) { if (!k) return; if (find(k)!=x) size[x]+=size[find(k)],fa[find(k)]=x; dfs(lson,x),dfs(rson,x); } void addedge(int x,int y) { if (find2(x)!=find2(y)) link(x,y); else { makeroot(x),access(y),splay(y); dfs(tree[y].ch[0],y);tree[y].ch[0]=0; } } int main() { #ifndef ONLINE_JUDGE freopen("bzoj4998.in","r",stdin); freopen("bzoj4998.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read(),q=read(); for (int i=1;i<=n;i++) fa[i]=i,fa2[i]=i,size[i]=1; for (int i=1;i<=m;i++) { int x=find(read()),y=find(read()); if (x!=y) addedge(x,y); } for (int i=1;i<=q;i++) { int x=find(read()),y=find(read()); if (x!=y) addedge(x,y); if (find(x)==find(y)) printf("%d\n",size[fa[x]]); else printf("No\n"); } return 0; }