1. 程式人生 > >洛谷 P2173 [ZJOI2012]網絡 解題報告

洛谷 P2173 [ZJOI2012]網絡 解題報告

文件 cat tmp 輸出格式 roo 不存在 數據規模 否則 data

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

洛谷 P2173 [ZJOI2012]網絡 解題報告