题意:维护一个动态并查集,支持加边,删边,维护两点连通性。
主要用到了 lct 的 Access FindRoot ChangeRoot link cut 操作。
#include<cstdio> #include<iostream> #include<stack> #include<cstring> #include<algorithm> using namespace std; #define maxn 10005 int fa[maxn],c[maxn][2],siz[maxn]; bool is_root[maxn],delta[maxn]; void Mark(int x){ if(x){ delta[x]^=1; } } void Maintain(int x) { siz[x]=siz[c[x][0]]+siz[c[x][1]]+1; } void pushdown(int x){ if(delta[x]){ Mark(c[x][0]); Mark(c[x][1]); swap(c[x][0],c[x][1]); delta[x]=0; } } void Rotate(int x,bool flag) { int y=fa[x]; c[y][!flag]=c[x][flag]; if(c[x][flag]){ fa[c[x][flag]]=y; } if(fa[y] && c[fa[y]][c[fa[y]][1]==y]==y){ c[fa[y]][c[fa[y]][1]==y]=x; } fa[x]=fa[y]; c[x][flag]=y; fa[y]=x; if(is_root[y]){ is_root[y]=0; is_root[x]=1; } Maintain(y); Maintain(x); } stack<int>st; void Splay(int x) { pushdown(x); if(!x || is_root[x]){ return; } int U=x; while(!is_root[U]){ st.push(U); U=fa[U]; } st.push(U); while(!st.empty()){ pushdown(st.top()); st.pop(); } int y; while(y=fa[x],(!is_root[x])){ if(is_root[y]){ Rotate(x,c[y][0]==x); } else{ if((c[y][0]==x)==(c[fa[y]][0]==y)){ Rotate(y,c[fa[y]][0]==y); } else{ Rotate(x,c[y][0]==x); y=fa[x]; } Rotate(x,c[y][0]==x); } } Maintain(x); } void Access(int x){ int y; Splay(x); while(fa[x]){ y=fa[x]; Splay(y); Splay(x); if(c[y][1]){ is_root[c[y][1]]=1; } is_root[x]=0; c[y][1]=x; Splay(x); } if(c[x][1]){ is_root[c[x][1]]=1; c[x][1]=0; } } void ChangeRoot(int x){ Access(x); Splay(x); Mark(x); } void cut(int x){ Access(x); Splay(x); fa[c[x][0]]=0; if(c[x][0]){ is_root[c[x][0]]=1; } c[x][0]=0; } void link(int x,int y){ Access(x); Splay(x); // Mark(c[x][0]); Access(y); Splay(y); c[y][1]=x; fa[x]=y; is_root[x]=0; } int FindRoot(int x){ Access(x); Splay(x); while(c[x][0]){ x=c[x][0]; } return x; } int n,m; int main(){ // freopen("bzoj2049.in","r",stdin); char op[10]; int x,y; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ siz[i]=1; is_root[i]=1; } for(int i=1;i<=m;++i){ scanf("%s%d%d",op,&x,&y); if(op[0]=='Q'){ puts(FindRoot(x)==FindRoot(y) ? "Yes" : "No"); } else if(op[0]=='C'){ ChangeRoot(x); link(x,y); } else{ if(FindRoot(x)==FindRoot(y)){ ChangeRoot(x); cut(y); } } } return 0; }