link cut tree(配套代码及题目)

1.bzoj 2002 弹飞绵羊

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
 
using namespace std;
 
#define MAXN (200000+5)
 
struct LCT{
    int fa[MAXN], ch[MAXN][2], size[MAXN];
    
    bool isroot(int o){
        return (o != ch[fa[o]][0] && o != ch[fa[o]][1]);
    }
    
    void push_up(int o){
         int lc = ch[o][0], rc = ch[o][1];
         size[o] = 1;
         if(lc) size[o] += size[lc];
         if(rc) size[o] += size[rc];
    }
    
    void rotate(int o){
        int f = fa[o], g = fa[f];
        int c = o == ch[f][1];
        
        if(!isroot(f)){
            if(ch[g][0] == f) ch[g][0] = o;
            else if(ch[g][1] == f) ch[g][1] = o;
        }
        
        fa[f] = o; fa[o] = g;
        fa[ch[o][c^1]] = f;
        
        ch[f][c] = ch[o][c^1];
        ch[o][c^1] = f;
        
        push_up(f);
    }
    
    void splay(int o){
        while(!isroot(o)){
            int f = fa[o], g = fa[f];
            if(isroot(f)){
                rotate(o);
                break;
            }
            
            if(!isroot(g)) rotate(f);
            rotate(o);
        }
        push_up(o);
    }
     
    void access(int o){
        int c = 0;
        while(o){
            splay(o);
            ch[o][1] = c;
            
            push_up(o);
            c = o;
            o = fa[o];
        }
    }
    
    void cut(int v){
        access(v);
        splay(v);
        fa[ch[v][0]] = 0;
        ch[v][0] = 0;
        push_up(v);
    }
    
    void link(int v, int w){
        cut(v);
        fa[v] = w;
    }
};
 
LCT SP;
 
int main(){
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
    
    int n;
    scanf("%d", &n);
    
    for(int i = 1; i <= n; i++){
        int bon;
        scanf("%d", &bon);
        
        SP.fa[i] = (i+bon) > n? 0: (i+bon);
        SP.size[i] = 1;
    }
    
    SP.size[0] = 0;
   
    int m;
    scanf("%d", &m);
    
    for(int i = 1; i <= m; i++){
        int op, j;
        scanf("%d%d", &op, &j);
        
        j++;
        if(op == 1){
            SP.access(j);
            SP.splay(j);
            printf("%d\n", SP.size[SP.ch[j][0]]+1);
        }else{
            int k;
            scanf("%d", &k);
            
            if(j+k > n) SP.link(j, 0);
            else SP.link(j, j+k);
        }
    }
    
    return 0;
}

2.bzoj 2049

洞穴勘测

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<stack>
 
using namespace std;
 
#define MAXN (10000+5)
 
int fa[MAXN], c[MAXN][2];
bool rev[MAXN];
 
void push_down(int x){
    int l = c[x][0], r = c[x][1];
    if(rev[x]){
        rev[x] ^= 1; rev[l] ^= 1; rev[r] ^= 1;
        swap(c[x][0], c[x][1]);
    }
}
 
bool isroot(int x){
    return (c[fa[x]][0] != x && c[fa[x]][1] != x);
}
 
void rotate(int o, int k){
    int son = c[o][k], f = fa[o], grand = fa[f];
 
    if(!isroot(f)){
        if(c[grand][0] == f) c[grand][0] = o;
        else c[grand][1] = o;
    }
 
    fa[o] = grand; fa[f] = o; 
    fa[son] = f;
    c[f][k^1] = son;
    c[o][k] = f;    
}
 
void splay(int x){
    stack<int> st;
    st.push(x);
 
    for(int i = x; !isroot(i); i = fa[i]) st.push(fa[i]);
    while(!st.empty()) push_down(st.top()), st.pop();
 
    while(!isroot(x)){
        if(x == c[fa[x]][0]) rotate(x, 1);
        else rotate(x, 0);
    }
}
 
void access(int x){
    int y = 0;
    while(x){
        splay(x);
        c[x][1] = y;
        y = x;
        x = fa[x];
    }
}
 
void rever(int x){
    access(x); splay(x); rev[x] ^= 1;
}
 
void cut(int x, int y){
    rever(x); access(y);
    splay(y);
 
    c[y][0] = fa[x] = 0;
}
 
void link(int x, int y){
    rever(x); fa[x] = y;
}
 
int find(int x){
    access(x); splay(x);
    while(c[x][0]) x = c[x][0];
    return x;
}
 
int main(){
    char r[10];
    int n, m;
    scanf("%d%d", &n, &m);
 
    for(int i = 1; i <= m; i++){
        int u, v;
        scanf("%s%d%d", r, &u, &v);
 
        if(r[0] == 'C') link(u, v);
        else if(r[0] == 'D') cut(u, v);
        else{
            int x = find(u), y = find(v);
            if(x == y) printf("Yes\n");
            else printf("No\n");
        }
    }
     
    return 0;
}


3.zjoi 2012 网络

题目描述

 有一个无向图G,每个点有个权值,每条边有一个颜色。这个无向图满足以下两个条件:

  1. 对于任意节点连出去的边中,相同颜色的边不超过两条。

  2. 图中不存在同色的环,同色的环指相同颜色的边构成的环。

在这个图上,你要支持以下三种操作:

  1. 修改一个节点的权值。

  2. 修改一条边的颜色。

  3. 查询由颜色c的边构成的图中,所有可能在节点u到节点v之间的简单路径上的节点的权值的最大值。

输入输出格式

输入格式:

输入文件network.in的第一行包含四个正整数N, M, C, K,其中N为节点个数,M为边数,C为边的颜色数,K为操作数。

接下来N行,每行一个正整数vi,为节点i的权值。

之后M行,每行三个正整数u, v, w,为一条连接节点u和节点v的边,颜色为w。满足1 ≤ u, v ≤ N,0 ≤ w < C,保证u ≠ v,且任意两个节点之间最多存在一条边(无论颜色)。

最后K行,每行表示一个操作。每行的第一个整数k表示操作类型。

  1. k = 0为修改节点权值操作,之后两个正整数x和y,表示将节点x的权值vx修改为y。

  2. k = 1为修改边的颜色操作,之后三个正整数u, v和w,表示将连接节点u和节点v的边的颜色修改为颜色w。满足0 ≤ w < C。

  3. k = 2为查询操作,之后三个正整数c, u和v,表示查询所有可能在节点u到节点v之间的由颜色c构成的简单路径上的节点的权值的最大值。如果不存在u和v之间不存在由颜色c构成的路径,那么输出“-1”。
输出格式:

输出文件network.out包含若干行,每行输出一个对应的信息。

  1. 对于修改节点权值操作,不需要输出信息。

  2. 对于修改边的颜色操作,按以下几类输出:

a) 若不存在连接节点u和节点v的边,输出“No such edge.”。

b) 若修改后不满足条件1,不修改边的颜色,并输出“Error 1.”。

c) 若修改后不满足条件2,不修改边的颜色,并输出“Error 2.”。

d) 其他情况,成功修改边的颜色,并输出“Success.”。

输出满足条件的第一条信息即可,即若同时满足b和c,则只需要输出“Error 1.”。

  1. 对于查询操作,直接输出一个整数。

输入输出样例

输入样例#1:
4 5 2 7
1
2
3
4
1 2 0
1 3 1
2 3 0
2 4 1
3 4 0
2 0 1 4
1 1 2 1
1 4 3 1
2 0 1 4
1 2 3 1
0 2 5
2 1 1 4
输出样例#1:
4
Success.
Error 2.
-1
Error 1.
5

说明

颜色0为实线的边,颜色1为虚线的边,

由颜色0构成的从节点1到节点4的路径有1 – 2 – 4,故max{v1, v2, v4} = max{ 1, 2, 4 } = 4。

将连接节点1和节点2的边修改为颜色1,修改成功,输出“Success.”

将连接节点4和节点3的边修改为颜色1,由于修改后会使得存在由颜色1构成的环( 1 – 2 – 4 – 3 – 1 ),不满足条件2,故不修改,并输出“Error 2”。

不存在颜色0构成的从节点1到节点4的边,输出“-1”。

将连接节点2和节点3的边修改为颜色1,由于修改后节点2的连出去的颜色为1的边有3条,故不满足条件1,故不修改,并输出“Error 1.”。

将节点2的权值修改为5。

由颜色1构成的从节点1到节点4的路径有 1 – 2 – 4,故max{v1, v2, v4} = max{ 1, 5, 4 } = 5。

【数据规模】

对于30%的数据:N ≤ 1000,M ≤ 10000,C ≤ 10,K ≤ 1000。

另有20%的数据:N ≤ 10000,M ≤ 100000,C = 1,K ≤ 100000。

对于100%的数据:N ≤ 10000,M ≤ 100000,C ≤ 10,K ≤ 100000。


本题的splay做法(已做),段大神的blog^-^: 点这里!!!

here is my LCT:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>

using namespace std;

#define LL long long
#define pb push_back
#define Set(a, v) memset(a, v, sizeof(a))
#define For(i, a, b) for(int i = (a); i <= (int)(b); i++)
#define Forr(i, a, b) for(int i = (a); i >= (int)(b); i--)

#define MAXN (10000+5)
#define MAXM (100000+5)
#define MAXC (10+5)

void read(int &x){
    char ch = getchar();
    while(ch < '0' || ch > '9') ch = getchar();

    x = 0;
    while(ch >= '0' && ch <= '9'){
        x = x*10 + ch -'0';
        ch = getchar();
    }
}

int val[MAXN], st[MAXN], top;

struct LCT{
    int ch[MAXN][2], fa[MAXN];
    int maxv[MAXN], rev[MAXN], du[MAXN];
    
    inline void maintain(int now){
        maxv[now] = val[now];
        if(ch[now][0]) maxv[now] = max(maxv[now], maxv[ch[now][0]]);
        if(ch[now][1]) maxv[now] = max(maxv[now], maxv[ch[now][1]]);
    }

    inline void push_down(int o){
        if(!rev[o]) return;
        int &lc = ch[o][0], &rc = ch[o][1];

        rev[lc] ^= 1; rev[rc] ^= 1; rev[o] ^= 1;
        swap(lc, rc);
    }

    inline bool isroot(int o){
        return (o != ch[fa[o]][0] && o != ch[fa[o]][1]);
    }

    inline void rotate(int o){
        int f = fa[o], g = fa[f];
        int c = (o == ch[f][1]);
        
        if(!isroot(f)){
            if(ch[g][0] == f) ch[g][0] = o;
            else ch[g][1] = o;
        }

        fa[f] = o; fa[o] = g;
        fa[ch[o][c^1]] = f;
        ch[f][c] = ch[o][c^1]; ch[o][c^1] = f;
        
        maintain(f);
    }

    inline void splay(int x){
        top = 0;

        st[++top] = x;
        for(int i = x; !isroot(i); i = fa[i]) st[++top] = fa[i];
        while(top){
            push_down(st[top]); top--;
        }

        int o = x;
        while(!isroot(o)){
            int f = fa[o], g = fa[f];
            if(isroot(f)){
                rotate(o);
                break;
            }

            if(!isroot(g)) rotate(f);
            rotate(o);
        }
        maintain(o);
    }

    inline void access(int x){
        int y = 0;

        while(x){
            splay(x);
            ch[x][1] = y;
            maintain(x);
            y = x;
            x = fa[x];
        }
    }

    inline void rever(int x){
        access(x); splay(x); rev[x] ^= 1;
    }

    inline void link(int x, int y){
        du[x]++; du[y]++;
        rever(x); fa[x] = y;
    }

    inline void cut(int x, int y){
        du[x]--; du[y]--;
        rever(x); access(y); splay(y);
        ch[y][0] = fa[x] = 0;

        maintain(y);
    }

    inline int find(int x){
        access(x); splay(x);

        int ret = x;
        while(ch[ret][0]) ret = ch[ret][0];
        return ret;
    }

    inline int query(int x, int y){
        rever(x); access(y); splay(y);
        return maxv[y];
    }
};

struct UV{
    int u, v;

    bool operator <(const UV &rhs)const{
        if(u != rhs.u) return u < rhs.u;
        return v < rhs.v;
    }
};

LCT lcts[MAXC];
map<UV, int> ms;

int main(){
    int n, m, c, k, u, v, w, op, x;

    read(n); read(m); read(c); read(k);
    For(i, 1, n) read(val[i]);

    For(i, 1, m){
        read(u); read(v); read(w);
        w++;

        UV t1 = (UV){u, v}, t2 = (UV){v, u};
        ms[t1] = ms[t2] = w;
        
        lcts[w].link(u, v);
    }

    For(ca, 1, k){
        read(op);
    //    printf("op = %d\n", op);

        if(op == 0){
            read(x); read(w);

            val[x] = w;
            For(i, 1, c) lcts[i].splay(x);
        }else if(op == 1){
            read(u); read(v); read(w);
            w++;
            
            UV tmp = (UV){u, v}, t2 = (UV){v, u};
            if(!ms.count(tmp)){
                printf("No such edge.\n");
                continue;
            }

            int bef = ms[tmp];
            if(bef == w){
                printf("Success.\n");
                continue;
            }

            if(lcts[w].du[u] >= 2 || lcts[w].du[v] >= 2){
                printf("Error 1.\n");
                continue;
            }

            if(lcts[w].find(u) == lcts[w].find(v)){
                printf("Error 2.\n");
                continue;
            }
            
            printf("Success.\n");
            lcts[bef].cut(u, v); lcts[w].link(u, v);
            ms[tmp] = ms[t2] = w;
        }else{
            read(w); read(u); read(v);
            w++;

            if(lcts[w].find(u) != lcts[w].find(v)){
                 printf("-1\n");
                continue;
            }
    
            printf("%d\n", lcts[w].query(u, v));
        }
    }

    return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值