BZOJ 2049, 洞穴勘測

Problem

傳送門

Mean

要求編寫一個數據結構,支持動態連邊、刪邊和查詢兩點連通性。
保證兩點間最多隻有一條路徑。

Analysis

LCT模板題。
(其實並查集更好些?)
借這題大致瞭解了一下LCT,順便回顧了一下Splay。
LCT裏的Splay略有不同於普通的Splay,也是需要特別注意的。

參考資料:Yang Zhe《SPOJ375 QTREE 解法的一些研究》

Code

#include<cstdio>
const int N=10005;
int n,m,x,y,f[N],son[N][2],tmp[N];
bool rev[N];
char s[10];
int read(){
    char c;
    while((c=getchar())<'0' || c>'9');
    int x=c-'0';
    while((c=getchar())>='0' && c<='9') x=x*10+c-'0';
    return x;
}
bool isroot(int x){return !f[x] || son[f[x]][0]!=x && son[f[x]][1]!=x;}
void swap(int &x,int &y){int t=x;x=y,y=t;}
void revl(int x){if(!x) return;swap(son[x][0],son[x][1]);rev[x]^=1;}
void pb(int x){if(rev[x]) revl(son[x][0]),revl(son[x][1]),rev[x]=0;}
void rotate(int x){
    int y=f[x],w=son[y][1]==x;
    son[y][w]=son[x][w^1];
    if(son[x][w^1]) f[son[x][w^1]]=y;
    if(!isroot(y)) son[f[y]][son[f[y]][1]==y]=x;
    f[x]=f[y];f[y]=x;son[x][w^1]=y;
}
void splay(int x){
    int s=1,i=x,y;
    tmp[1]=i;
    while(!isroot(i)) tmp[++s]=i=f[i];
    while(s) pb(tmp[s--]);
    while(!isroot(x)){
        y=f[x];
        if(!isroot(y)){
            if((son[f[y]][0]==y)^(son[y][0]==x)) rotate(x);
            else rotate(y);
        }
        rotate(x);
    }
}
void access(int x){for(int y=0;x;y=x,x=f[x]) splay(x),son[x][1]=y;}
int root(int x){access(x);splay(x);while(son[x][0]) x=son[x][0];return x;}
void makeroot(int x){access(x);splay(x);revl(x);}
void link(int x,int y){makeroot(x);f[x]=y;access(x);}
void cutf(int x){access(x);splay(x);f[son[x][0]]=0;son[x][0]=0;}
void cut(int x,int y){makeroot(x);cutf(y);}
int main(){
    n=read(),m=read();
    while(m--){
        scanf("%s",s);
        x=read(),y=read();
        if(s[0]=='C') link(x,y);
        else if(s[0]=='D') cut(x,y);
        else if(root(x)!=root(y)) printf("No\n");
        else printf("Yes\n");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章