BZOJ 2049: [Sdoi2008]Cave 洞穴勘测

Fancy posted @ 2015年7月10日 00:00 in BZOJ , 292 阅读

题目大意:有三种操作:连接两个洞穴,摧毁两个洞穴的道路,询问两个洞穴是否联通

动态树,可以link和cut,询问的时候判断一下它们的根是否相同就行了

#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN = 10010;
int ch[MAXN][2],pre[MAXN];
int rev[MAXN];
bool rt[MAXN];
void Update_Rev(int r)
{
    if(!r)return;
    swap(ch[r][0],ch[r][1]);
    rev[r] ^= 1;
}
void push_down(int r)
{
    if(rev[r])
    {
        Update_Rev(ch[r][0]);
        Update_Rev(ch[r][1]);
        rev[r] = 0;
    }
}
void Rotate(int x)
{
    int y = pre[x], kind = ch[y][1]==x;
    ch[y][kind] = ch[x][!kind];
    pre[ch[y][kind]] = y;
    pre[x] = pre[y];
    pre[y] = x;
    ch[x][!kind] = y;
    if(rt[y])
        rt[y] = false, rt[x] = true;
    else
        ch[pre[x]][ch[pre[x]][1]==y] = x;
}
void P(int r)
{
    if(!rt[r])P(pre[r]);
    push_down(r);
}
void Splay(int r)
{
    P(r);
    while( !rt[r] )
    {
        int f = pre[r], ff = pre[f];
        if(rt[f])
            Rotate(r);
        else if( (ch[ff][1]==f)==(ch[f][1]==f) )
            Rotate(f), Rotate(r);
        else
            Rotate(r), Rotate(r);
    }
}
int Access(int x)
{
    int y = 0;
    do
    {
        Splay(x);
        rt[ch[x][1]] = true, rt[ch[x][1]=y] = false;
        x = pre[y=x];
    }
    while(x);
    return y;
}
bool judge(int u,int v)
{
    while(pre[u]) u = pre[u];
    while(pre[v]) v = pre[v];
    return u == v;
}
void mroot(int r)
{
    Access(r);
    Splay(r);
    Update_Rev(r);
}
void link(int u,int v)
{
    mroot(u);
    pre[u] = v;
}
void cut(int u,int v)
{
    mroot(u);
    Splay(v);
    pre[ch[v][0]] = pre[v];
    pre[v] = 0;
    rt[ch[v][0]] = true;
    ch[v][0] = 0;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
        for(int i = 0;i <= n;i++)
        {
            pre[i] = 0;
            ch[i][0] = ch[i][1] = 0;
            rev[i] = 0;
            rt[i] = true;
        }
        char op[20];
        int u,v;
        while(m--)
        {
            scanf("%s%d%d",op,&u,&v);
            if(op[0] == 'Q')
            {
                if(judge(u,v))printf("Yes\n");
                else printf("No\n");
            }
            else if(op[0] == 'C')
                link(u,v);
            else cut(u,v);
        }
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter