洛谷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\n",tr[cc].sum[y]);
        }
    }
}

 




posted @ 2018-08-13 22:15  Styx-ferryman  阅读(158)  评论(0编辑  收藏  举报