【BZOJ】2049: [Sdoi2008]Cave 洞穴勘测 LCT
【题意】给定n个点和m个操作,每次操作:1.连接2个点。2.断开2个点。3.查询2个点是否连通。m<=2*10^5。
【算法】Link-Cut Tree
【题解】LCT模板题,Link,Cut,和查询两个点的root是否相同。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; int read(){ int s=0,t=1;char c; while(!isdigit(c=getchar()))if(c=='-')t=-1; do{s=s*10+c-'0';}while(isdigit(c=getchar())); return s*t; } const int maxn=10010; int t[maxn][2],f[maxn],g[maxn],a[maxn]; bool isroot(int x){return !x||(t[f[x]][0]!=x&&t[f[x]][1]!=x);}// void down(int x){ if(g[x]){ swap(t[x][0],t[x][1]); g[t[x][0]]^=1;g[t[x][1]]^=1; g[x]=0; } } void rotate(int y){ int x=f[y]; int k=y==t[x][0]; t[x][!k]=t[y][k];f[t[y][k]]=x; if(!isroot(x))t[f[x]][x==t[f[x]][1]]=y;f[y]=f[x];f[x]=y; t[y][k]=x; } void splay(int x){ int top=x,tot=1;a[1]=x; while(!isroot(top))top=f[top],a[++tot]=top; for(int i=tot;i>=1;i--)down(a[i]); while(!isroot(x)){//top X if(isroot(f[x])){rotate(x);break;} int X=x==t[f[x]][1],Y=f[x]==t[f[f[x]]][1]; if(X^Y)rotate(x),rotate(x); else rotate(f[x]),rotate(x); } } void access(int x){ int y=0; while(x){ splay(x); t[x][1]=y; y=x;x=f[x]; } } void reserve(int x){access(x);splay(x);g[x]^=1;} void link(int x,int y){reserve(x);f[x]=y;} void cut(int x,int y){reserve(x);access(y);splay(y);t[y][0]=f[x]=0;} int root(int x){access(x);splay(x);while(t[x][0])x=t[x][0];return x;} char s[10]; int main(){ int n=read(),m=read(); while(m--){ scanf("%s",s); int x=read(),y=read(); if(s[0]=='C')link(x,y); if(s[0]=='D')cut(x,y); if(s[0]=='Q'){if(root(x)==root(y))printf("Yes\n");else printf("No\n");} } return 0; }