• 洛谷 P2173 [ZJOI2012]网络 解题报告


    P2173 [ZJOI2012]网络

    题目描述

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

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

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

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

    修改一个节点的权值。

    修改一条边的颜色。

    查询由颜色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表示操作类型。

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

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

    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.”。

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

    数据规模

    对于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。


    说实话题目并不难,发现(C<=10)以后我们就可以暴力对每种颜色建一个LCT搞一搞了

    这里我用map判断是否直接相连

    条件1统计度,条件2看联通

    注意要特判更改前后的颜色是否相同(否则会被判成2)

    我调了N久。。码力太差了


    Code:

    #include <cstdio>
    #include <cstring>
    #include <map>
    using namespace std;
    const int N=1e5+10;
    int max(int x,int y){return x>y?x:y;}
    int mx[N],val[N],ch[N][2],par[N],tag[N],s[N],tot;
    #define ls ch[now][0]
    #define rs ch[now][1]
    #define fa par[now]
    bool isroot(int now){return ch[fa][0]==now||ch[fa][1]==now;}
    int identity(int now){return ch[fa][1]==now;}
    void connect(int f,int now,int typ){fa=f;ch[f][typ]=now;}
    void Reverse(int now){int tmp=ls;ls=rs,rs=tmp;tag[now]^=1;}
    void updata(int now){mx[now]=max(val[now],max(mx[ls],mx[rs]));}
    void Rotate(int now)
    {
        int p=fa,typ=identity(now);
        connect(p,ch[now][typ^1],typ);
        if(isroot(p)) connect(par[p],now,identity(p));
        else  fa=par[p];
        connect(now,p,typ^1);
        updata(p),updata(now);
    }
    void pushdown(int now)
    {
        if(tag[now])
        {
            if(ls) Reverse(ls);
            if(rs) Reverse(rs);
            tag[now]^=1;
        }
    }
    void splay(int now)
    {
        while(isroot(now)) s[++tot]=now,now=fa;
        s[++tot]=now;
        while(tot) pushdown(s[tot--]);
        now=s[1];
        for(;isroot(now);Rotate(now))
            if(isroot(fa))
                Rotate(identity(now)^identity(fa)?now:fa);
    }
    void access(int now)
    {
        for(int las=0;now;las=now,now=fa)
            splay(now),rs=las,updata(now);
    }
    void evert(int now){access(now),splay(now),Reverse(now);}
    void link(int u,int v)
    {
        evert(u);par[u]=v;
    }
    void cat(int u,int v)
    {
        evert(u),access(v),splay(v);
        ch[v][0]=par[u]=0;
        updata(v);
    }
    void change(int now,int va)
    {
        splay(now),val[now]=va,updata(now);
    }
    int findroot(int now)
    {
        access(now),splay(now);
        while(ls)
            now=ls;
        return now;
    }
    int query(int u,int v)
    {
        evert(u),access(v),splay(v);
        if(findroot(v)!=u) return -1;
        return mx[v];
    }
    int n,m,c,k,du[N];
    map <int,int> ma[N/10];
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&c,&k);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",val+i);
            mx[i]=val[i];
            for(int j=1;j<c;j++)
                val[j*n+i]=val[i],mx[j*n+i]=val[i];
        }
        for(int u,v,w,i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            ma[u][v]=ma[v][u]=w+1;
            ++du[w*n+u],++du[w*n+v];
            link(w*n+u,w*n+v);
        }
        for(int op,u,v,w,i=1;i<=k;i++)
        {
            scanf("%d%d%d",&op,&u,&v);
            if(op==0)
            {
                for(int j=0;j<c;j++)
                    change(u+j*n,v);
            }
            else if(op==1)
            {
                scanf("%d",&w);
                if(!ma[u][v])
                {
                    printf("No such edge.
    ");
                    continue;
                }
                if(ma[u][v]==w+1)
                {
                    printf("Success.
    ");
                    continue;
                }
                int lu=u+(ma[u][v]-1)*n,lv=v+(ma[u][v]-1)*n,vv=v,uu=u;
                u+=w*n,v+=w*n;
                if(du[u]>1||du[v]>1)
                {
                    printf("Error 1.
    ");
                    continue;
                }
                if(findroot(u)==findroot(v))
                {
                    printf("Error 2.
    ");
                    continue;
                }
                ma[uu][vv]=ma[vv][uu]=w+1;
                --du[lu],--du[lv],++du[u],++du[v];
                printf("Success.
    ");
                cat(lu,lv);
                link(u,v);
            }
            else
            {
                scanf("%d",&w);
                printf("%d
    ",query(u*n+v,u*n+w));
            }
        }
        return 0;
    }
    
    

    2018.9.1

  • 相关阅读:
    UML 基础知识
    制作嵌入式根文件系统
    oracle 学习之 PL/SQL
    Password for '(null)' GNOME keyring:
    oracle 学习笔记
    lua关于编译后无法使用
    android,wince,windows,ios mms 网络电台收音机,小巧,兼容性好,性能高
    lua批量编译目前支持5.2,5.1
    lua关于编译后无法使用
    dlna support windows
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9571758.html
Copyright © 2020-2023  润新知