嘘~ 正在从服务器偷取页面 . . .

洛谷P2147 [SDOI2008] 洞穴勘测 题解


洛谷P2147 [SDOI2008] 洞穴勘测 题解

题目链接:P2147 [SDOI2008] 洞穴勘测

题意:给定若干个点,动态连接(无向边),询问连通性

由于它有删边的操作,因此用并查集并不可行

于是想到LCT(?

由于LCT有 find_root() 操作

说明LCT确实可以动态判定连通性

那么就变成简单的模板题了(

代码如下

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N (int)(1e4+5)
int n,Q;
namespace LCT
{
    struct node
    {
        int ch[2],fa,tag;
    }t[N];
    #define isroot(x) ((t[t[x].fa].ch[0]!=x)&&(t[t[x].fa].ch[1]!=x))
    void pushr(int x)
    {
        swap(t[x].ch[0],t[x].ch[1]);
        t[x].tag^=1;
    }
    void push_down(int x)
    {
        if(t[x].tag)
        {
            if(t[x].ch[0])pushr(t[x].ch[0]);
            if(t[x].ch[1])pushr(t[x].ch[1]);
            t[x].tag=0;
        }
    }
    void push_all(int x)
    {
        if(!isroot(x))push_all(t[x].fa);
        push_down(x);
    }
    void rotate(int x)
    {
        int y=t[x].fa;
        int z=t[y].fa;
        int k=t[y].ch[1]==x;
        if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;
        t[x].fa=z;
        t[y].ch[k]=t[x].ch[k^1];
        t[t[x].ch[k^1]].fa=y;
        t[x].ch[k^1]=y;
        t[y].fa=x;
    }
    void splay(int x)
    {
        push_all(x);
        while(!isroot(x))
        {
            int y=t[x].fa;
            int z=t[y].fa;
            if(!isroot(y))
            (t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y);
            rotate(x);
        }
    }
    void access(int x)
    {
        for(int y=0; x; y=x,x=t[x].fa)
            splay(x),t[x].ch[1]=y;
    }
    void make_root(int x)
    {
        access(x);splay(x);
        pushr(x);
    }
    int find_root(int x)
    {
        access(x);splay(x);
        while(t[x].ch[0])push_down(x),x=t[x].ch[0];
        splay(x);
        return x;
    }
    void link(int x,int y)
    {
        make_root(x);
        if(find_root(y)!=x)t[x].fa=y;
    }
    void cut(int x,int y)
    {
        make_root(x);
        if(find_root(y)==x&&t[y].fa==x&&!t[y].ch[0])
            t[y].fa=t[x].ch[1]=0;
    }
}
signed main()
{
    using namespace  LCT;
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin >> n >> Q;
    while(Q--)
    {
        string str;int x,y;
        cin >> str >> x >> y;
        if(str[0]=='Q')
        {
            make_root(x);
            access(y);
            if(find_root(y)!=x)cout << "No" << endl;
            else cout << "Yes" << endl;
        }
        if(str[0]=='C') link(x,y);
        if(str[0]=='D') cut(x,y);
    }
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录