洛谷 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.\n");
                continue;
            }
            if(ma[u][v]==w+1)
            {
                printf("Success.\n");
                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.\n");
                continue;
            }
            if(findroot(u)==findroot(v))
            {
                printf("Error 2.\n");
                continue;
            }
            ma[uu][vv]=ma[vv][uu]=w+1;
            --du[lu],--du[lv],++du[u],++du[v];
            printf("Success.\n");
            cat(lu,lv);
            link(u,v);
        }
        else
        {
            scanf("%d",&w);
            printf("%d\n",query(u*n+v,u*n+w));
        }
    }
    return 0;
}

2018.9.1

猜你喜欢

转载自www.cnblogs.com/ppprseter/p/9571758.html