【BZOJ2049】[Sdoi2008]Cave 洞穴勘测【Link-Cut Tree】

就不发题意了...


LCT模板题,和http://www.spoj.com/problems/DYNACON1/一样,但是不卡常数。


并查集做法见:http://blog.csdn.net/braketbn/article/details/50733104


数组:

#include <cstdio>
#include <algorithm>
 
using namespace std;
 
const int maxn = 100005;
 
int n, m, son[maxn][2], pre[maxn];
bool rev[maxn];
 
inline int iread() {
    int f = 1, x = 0; char ch = getchar();
    for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
    for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
    return f * x;
}
 
inline bool isroot(int x) {
    return son[pre[x]][0] != x && son[pre[x]][1] != x;
}
 
inline void pushdown(int x) {
    if(rev[x]) {
        rev[son[x][0]] ^= 1; rev[son[x][1]] ^= 1;
        swap(son[x][0], son[x][1]);
        rev[x] = 0;
    }
}
 
int sta[maxn];
inline void maintain(int x) {
    int top = 0;
    for(sta[++top] = x; !isroot(x); x = pre[x]) sta[++top] = pre[x];
    for(; top; pushdown(sta[top--]));
}   
 
inline void rotate(int x) {
    int y = pre[x], z = pre[y], type = son[y][1] == x;
    pre[son[y][type] = son[x][!type]] = y;
    pre[x] = z;
    if(!isroot(y)) son[z][son[z][1] == y] = x;
    pre[son[x][!type] = y] = x;
}
 
inline void splay(int x) {
    maintain(x);
    while(!isroot(x)) {
        int y = pre[x], z = pre[y];
        if(isroot(y)) rotate(x);
        else if(son[z][1] == y ^ son[y][1] == x) rotate(x), rotate(x);
        else rotate(y), rotate(x);
    }
}
 
inline void access(int x) {
    for(int y = 0; x; x = pre[y = x]) {
        splay(x);
        son[x][1] = y;
    }
}
 
inline void makeroot(int x) {
    access(x); splay(x); rev[x] ^= 1;
}
 
inline int findroot(int x) {
    access(x); splay(x);
    for(; son[x][0]; x = son[x][0]);
    return x;
}
 
inline void link(int a, int b) {
    makeroot(a); pre[a] = b;
}
 
inline void cut(int a, int b) {
    makeroot(a); access(b); splay(b);
    son[b][0] = pre[a] = 0;
}
 
inline bool check(int a, int b) {
    if(findroot(a) == findroot(b)) return 1;
    return 0;
}
 
int main() {
    n = iread(); m = iread();
    while(m--) {
        char ch = getchar(); for(; ch != 'C' && ch != 'D' && ch != 'Q'; ch = getchar());
        int a = iread(), b = iread();
        if(ch == 'C') link(a, b);
        else if(ch == 'D') cut(a, b);
        else printf(check(a, b) ? "Yes\n" : "No\n");
    }
    return 0;
}

指针:

#include <cstdio>
#include <algorithm>
 
using namespace std;
 
const int maxn = 100005;
 
int n, m;
 
struct node {
    node *son[2], *pre;
    bool rev;
} pool[maxn], *null;
 
inline int iread() {
    int f = 1, x = 0; char ch = getchar();
    for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
    for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
    return f * x;
}
 
inline bool isroot(node *x) {
    return x->pre->son[0] != x && x->pre->son[1] != x;
}
 
inline void pushdown(node *x) {
    if(x->rev) {
        x->son[0]->rev ^= 1; x->son[1]->rev ^= 1;
        swap(x->son[0], x->son[1]);
        x->rev = 0;
    }
}
 
node *sta[maxn];
inline void maintain(node *x) {
    int top = 0;
    for(sta[++top] = x; !isroot(x); x = x->pre) sta[++top] = x->pre;
    for(; top; pushdown(sta[top--]));
}
 
inline void rotate(node *x) {
    node *y = x->pre, *z = y->pre; int type = y->son[1] == x;
    y->son[type] = x->son[!type];
    x->son[!type]->pre = y;
    x->pre = z;
    if(!isroot(y)) z->son[z->son[1] == y] = x;
    x->son[!type] = y;
    y->pre = x;
}
 
inline void splay(node *x) {
    maintain(x);
    while(!isroot(x)) {
        node *y = x->pre, *z = y->pre;
        if(isroot(y)) rotate(x);
        else if(z->son[1] == y ^ y->son[1] == x) rotate(x), rotate(x);
        else rotate(y), rotate(x);
    }
}
 
inline void access(node *x) {
    for(node *y = null; x != null; x = x->pre) {
        splay(x);
        x->son[1] = y;
        y = x;
    }
}
 
inline void makeroot(node *x) {
    access(x); splay(x); x->rev ^= 1;
}
 
inline node* findroot(node* x) {
    access(x); splay(x);
    for(; x->son[0] != null; x = x->son[0]);
    return x;
}
 
inline void link(int x, int y) {
    node *a = pool + x, *b = pool + y;
    makeroot(a); a->pre = b;
}
 
inline void cut(int x, int y) {
    node *a = pool + x, *b = pool + y;
    makeroot(a); access(b); splay(b);
    b->son[0] = a->pre = pool;
}
 
inline bool check(int x, int y) {
    node *a = pool + x, *b = pool + y;
    if(findroot(a) == findroot(b)) return 1;
    return 0;
}
 
int main() {
    n = iread(); m = iread();
    null = pool; null->son[0] = null->son[1] = null->pre = null; null->rev = 0;
    for(int i = 1; i <= n; i++) {
        node *x = pool + i;
        x->son[0] = x->son[1] = x->pre = null;
        x->rev = 0;
    }
    while(m--) {
        char ch = getchar(); for(; ch != 'C' && ch != 'D' && ch != 'Q'; ch = getchar());
        int a = iread(), b = iread();
        if(ch == 'C') link(a, b);
        else if(ch == 'D') cut(a, b);
        else printf(check(a, b) ? "Yes\n" : "No\n");
    }
    return 0;
}


你可能感兴趣的:(tree,Link-Cut)