• 洛谷P2173 [ZJOI2012]网络(10棵lct与瞎jb暴力)


    有一个无向图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

    题解:这题写了两个小时才A掉,估计没人比我更菜了
    这题的语文要求还有点小高,我们一个一个来分析
    首先看到颜色个数很少,而且颜色会变,不难想到对每种颜色搞一颗lct
    那么第一个操作权值修改就是将每颗lct里的x rotate到当前splay的根,接着更新权值。
    第二个操作比较繁琐
    首先是没边的情况,因为题目保证了每个点相同颜色的边不超过两条,所以每个点最多有20条边,这样可以暴力遍历每一条边,查找是不是存在x到y的边。
    接着是边数超过两条的情况,很显然还是暴力搜每一条边,如果x和y两点有一点已经连接了两个该颜色,那就GG了
    接着是是否已经联通的问题,显然make_root然后find_root一下就可以了
    最后就是把原来颜色的lct里cut一下,现在lct里link一下就行了。
    第三个操作中规中矩
    就是splay里push_up一下,把x splay到根,接着输出答案就行了。

    最大的坑点——可能x到y的边被更新成原来的颜色,这样子操作二的第二种情况就会出锅,所以要优先处理一下,

    代码如下:
    #include<map>
    #include<set>
    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 10010
    #define mp make_pair
    #define lson ch[x][0]
    #define rson ch[x][1]
    #define pii pair<int,int>
    using namespace std;
    
    int w[N];
    
    struct lct
    {
        int sum[N],f[N],ch[N][2],tag[N];
    
        int not_root(int now)
        {
            int x=f[now];
            return lson==now||rson==now;
        }
    
        int push_up(int x)
        {
            sum[x]=max(max(sum[lson],sum[rson]),w[x]);
        }
    
        int rev(int x)
        {
            swap(lson,rson);
            tag[x]^=1;
        }
    
        int push_down(int x)
        {
            if(tag[x])
            {
                rev(lson);
                rev(rson);
                tag[x]^=1;
            }
        }
    
        int rotate(int x)
        {
            int y=f[x],z=f[y],kd=ch[y][1]==x,xs=ch[x][!kd];
            if(not_root(y))
            {
                ch[z][ch[z][1]==y]=x;
            }
            ch[x][!kd]=y;
            ch[y][kd]=xs;
            if(xs) f[xs]=y;
            f[y]=x;
            f[x]=z;
            push_up(y);
        }
    
        int push_all(int x)
        {
            if(not_root(x))
            {
                push_all(f[x]);
            }
            push_down(x);
        }
    
        int splay(int x)
        {
            int y,z;
            push_all(x);
            while(not_root(x))
            {
                y=f[x],z=f[y];
                if(not_root(y))
                {
                    (ch[y][0]==x)^(ch[z][0]==y)?rotate(x):rotate(y);
                }
                rotate(x);
            }
            push_up(x);
        }
    
        int access(int x)
        {
            for(int y=0; x; y=x,x=f[x])
            {
                splay(x);
                rson=y;
                push_up(x);
            }
        }
    
        int make_root(int x)
        {
            access(x);
            splay(x);
            rev(x);
        }
    
        int split(int x,int y)
        {
            make_root(x);
            access(y);
            splay(y);
        }
    
        int find_root(int x)
        {
            access(x);
            splay(x);
            while(lson)
            {
                push_down(x);
                x=lson;
            }
            return x;
        }
    
        int link(int x,int y)
        {
            make_root(x);
            if(find_root(y)==x) return 0;
            f[x]=y;
            return 1;
        }
    
        int cut(int x,int y)
        {
            make_root(x);
            if(find_root(y)!=x||f[x]!=y||rson) return 0;
            f[x]=ch[y][0]=0;
            return 1;
        }
        int print(int x)
        {
            if(lson) print(lson);
            printf("%d ",x);
            if(rson) print(rson);
        }
    } tr[11];
    
    vector<pii> g[10010];
    int n,m,c,k;
    
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&c,&k);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&w[i]);
        }
        int from,to,cl;
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d",&from,&to,&cl);
            tr[cl].link(from,to);
            g[from].push_back(mp(to,cl));
            g[to].push_back(mp(from,cl));
        }
        while(k--)
        {
            int kd,x,y,cc;
            scanf("%d",&kd);
            if(kd==0)
            {
                scanf("%d%d",&x,&y);
                for(int i=0; i<c; i++)
                {
                    tr[i].splay(x);
                }
                w[x]=y;
            }
            if(kd==1)
            {
                int flag=1,tot=0,tot2=0,pos;
                scanf("%d%d%d",&x,&y,&cc);
                for(int i=0; i<g[x].size(); i++)
                {
                    if(g[x][i].first==y)
                    {
                        flag=0;
                        pos=g[x][i].second;
                    }
                    if(g[x][i].second==cc)
                    {
                        tot++;
                    }
                }
                for(int i=0; i<g[y].size(); i++)
                {
                    if(g[y][i].second==cc)
                    {
                        tot2++;
                    }
                }
                tot=max(tot2,tot);
                if(flag)
                {
                    puts("No such edge.");
                    continue;
                }
                if(pos==cc)
                {
                    puts("Success.");
                    continue;
                }
                if(tot==2)
                {
                    puts("Error 1.");
                    continue;
                }
                tr[cc].make_root(x);
                if(tr[cc].find_root(y)==x)
                {
                    puts("Error 2.");
                    continue;
                }
                tr[pos].cut(x,y);
                tr[cc].link(x,y);
                for(int i=0; i<g[x].size(); i++)
                {
                    if(g[x][i].first==y)
                    {
                        g[x][i].second=cc;
                        break;
                    }
                }
                for(int i=0; i<g[y].size(); i++)
                {
                    if(g[y][i].first==x)
                    {
                        g[y][i].second=cc;
                        break;
                    }
                }
                puts("Success.");
            }
            if(kd==2)
            {
                scanf("%d%d%d",&cc,&x,&y);
                tr[cc].make_root(x);
                if(tr[cc].find_root(y)!=x)
                {
                    puts("-1");
                    continue;
                }
                printf("%d
    ",tr[cc].sum[y]);
            }
        }
    }



  • 相关阅读:
    闲置安卓设备搭建Linux服务器实现外网访问
    Flume笔记
    动态规划算法助记
    Hexo 添加Live2D看板娘
    Oracle 助记
    搭建Discuz论坛
    逆向工程(助记)
    PL/SQL Developer连接本地Oracle 11g 64位数据库
    NSOperation的基础
    GCD基础
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/9471407.html
Copyright © 2020-2023  润新知