码迷,mamicode.com
首页 > 其他好文 > 详细

luogu2173 [ZJOI2012]网络

时间:2020-02-26 17:07:17      阅读:49      评论:0      收藏:0      [点我收藏+]

标签:vector   bit   printf   需要   wap   tmp   int   type   oid   

题目链接

problem

给出一个无向图,每条边有一种颜色。每种颜色都构成一个森林。需要完成以下操作。

  • 修改点权
  • 修改边的颜色
  • 询问某种颜色的森林中某条路径上点权最大值

solution

颜色数量不超过10,所以对于每种颜色建一棵LCT。
修改点权,就对每种颜色的LCT都修改。
修改边的颜色,就将原来颜色的LCT中这条边断掉,在新颜色的LCT中加上。这里需要判断加入边后是否还满足是森林,所以需要统计每个点连出去的各种颜色点的数量。还要判断是否会形成环,只要判断原来两点是否在同一棵树中。
询问操作则直接询问即可。

code

/*
* @Author: wxyww
* @Date: 2020-02-26 07:36:20
* @Last Modified time: 2020-02-26 09:21:59
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<bitset>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
#define ls TR[cur].ch[0]
#define rs TR[cur].ch[1]
const int N = 10010;
ll read() {
    ll x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

struct LCT {
    struct node {
        int ch[2],val,rev,mx,pre;
    }TR[N];
    int isroot(int cur) {
        return TR[TR[cur].pre].ch[0] != cur && TR[TR[cur].pre].ch[1] != cur;
    }
    int getwh(int cur) {
        return TR[TR[cur].pre].ch[1] == cur;
    }
    void up(int cur) {
        TR[cur].mx = max(TR[ls].mx,max(TR[rs].mx,TR[cur].val));
    }
    void pushdown(int cur) {
        if(TR[cur].rev) {
            TR[ls].rev ^= 1;TR[rs].rev ^= 1;
            swap(ls,rs);
            TR[cur].rev = 0;
        }
    }
void rotate(int cur) {
    int fa = TR[cur].pre,gr = TR[fa].pre,f = getwh(cur);

    if(!isroot(fa)) TR[gr].ch[getwh(fa)] = cur;
    TR[cur].pre = gr;
    if(TR[cur].ch[f ^ 1]) TR[TR[cur].ch[f ^ 1]].pre = fa;
    TR[fa].ch[f] = TR[cur].ch[f ^ 1];
    TR[fa].pre = cur;TR[cur].ch[f ^ 1] = fa;
    up(fa);up(cur);
}
    int sta[N],top;
    void splay(int cur) {
        sta[++top] = cur;

        for(int i = cur;!isroot(i);i = TR[i].pre) {
            // printf("%d\n",i);
            sta[++top] = TR[i].pre;
        }
        while(top) pushdown(sta[top--]);

        while(!isroot(cur)) {
            if(!isroot(TR[cur].pre)) {
                if(getwh(TR[cur].pre) == getwh(cur)) rotate(TR[cur].pre);
                else rotate(cur);
            }
            rotate(cur);
        }
    }

    void access(int cur) {
        for(int t = 0;cur;t = cur,cur = TR[cur].pre) {

            splay(cur);rs = t;up(cur);
        }
    }
    void makeroot(int cur) {
        access(cur);

        splay(cur);
        TR[cur].rev ^= 1;
    }
    void link(int x,int y) {
        // printf("%d\n",x);
        makeroot(x);TR[x].pre = y;
    }

    void cut(int x,int cur) {
        makeroot(x);access(cur);
        splay(cur);
        ls = TR[ls].pre = 0;
        up(cur);
    }

    void update(int cur,int c) {
        makeroot(cur);TR[cur].val = c;
        up(cur);
    }
    int find(int cur) {
        access(cur);splay(cur);
        while(ls) cur = ls;
        return cur;
    }
    int query(int x,int y) {
        if(find(x) != find(y)) return -1;
        makeroot(x);access(y);splay(y);
        return TR[y].mx;
    }
}t[10];


#define pi pair<int,int>
map<pi,int>ma;
int num[N][11];
int main() {
    // freopen("1.in","r",stdin);
    int n = read(),m = read(),C = read(),Q = read();
    for(int i = 1;i <= n;++i) {
        int x = read();
        for(int j = 0;j < C;++j) 
        t[j].TR[i].mx = t[j].TR[i].val = x;
    }
    for(int i = 1;i <= m;++i) {
        int u = read(),v = read(),w = read();
        ma[make_pair(u,v)] = ma[make_pair(v,u)] = w;
        num[u][w]++;num[v][w]++;

        t[w].link(u,v);
        // puts("!!!");
    }

    while(Q--) {
        int opt = read();
        if(opt == 0) {
            int x = read(),y = read();
            for(int j = 0;j < C;++j) {
                t[j].update(x,y);
            }
        }

        if(opt == 1) {
            int u = read(),v = read(),w = read();
            if(!ma.count(make_pair(u,v))) {
                puts("No such edge.");continue;
            }
            int tmp = ma[make_pair(u,v)];
            if(tmp == w) {puts("Success.");continue;}
            
            if(num[u][w] + 1 > 2 || num[v][w] + 1 > 2) {puts("Error 1.");continue;}

            // printf("%d %d\n",t[w].find(u),t[w].find(v));
            if(t[w].find(u) == t[w].find(v)) {
                puts("Error 2.");continue;}


            puts("Success.");

            t[tmp].cut(u,v);

            num[u][tmp]--;num[v][tmp]--;

            num[u][w]++;num[v][w]++;
            t[w].link(u,v);
            ma[make_pair(u,v)] = ma[make_pair(v,u)] = w;
        }


        if(opt == 2) {
            int c = read(),u = read(),v = read();
            printf("%d\n",t[c].query(v,u));
        }
    }


    return 0;
}

luogu2173 [ZJOI2012]网络

标签:vector   bit   printf   需要   wap   tmp   int   type   oid   

原文地址:https://www.cnblogs.com/wxyww/p/luogu2173.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!