1. 程式人生 > >【BZOJ2816】【ZJOI2012】網絡(Link-Cut Tree)

【BZOJ2816】【ZJOI2012】網絡(Link-Cut Tree)

max 三種 ++i error 如果 描述 信息 logs fat

【BZOJ2816】【ZJOI2012】網絡(Link-Cut Tree)

題面

題目描述

有一個無向圖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包含若幹行,每行輸出一個對應的信息。

對於修改節點權值操作,不需要輸出信息。

對於修改邊的顏色操作,按以下幾類輸出:

a) 若不存在連接節點u和節點v的邊,輸出“No such edge.”。

b) 若修改後不滿足條件1,不修改邊的顏色,並輸出“Error 1.”。

c) 若修改後不滿足條件2,不修改邊的顏色,並輸出“Error 2.”。

d) 其他情況,成功修改邊的顏色,並輸出“Success.”。

輸出滿足條件的第一條信息即可,即若同時滿足b和c,則只需要輸出“Error 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

題解

考慮\(C<=10\)
那麽, 暴力維護\(C\)棵樹即可
直接\(LCT\)維護即可
細節真的是有點多。。。
這道題目慢慢做。。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MAX 11000
#define fat t[x].ff
#define lson t[x].ch[0]
#define rson t[x].ch[1]
inline int read()
{
    int x=0,t=1;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
int S[MAX],top;
struct N{int u,v;};
int n,m,C,K,val[MAX];
int color[MAX][11];
bool operator<(N a,N b)
{
    if(a.u!=b.u)return a.u<b.u;
    return a.v<b.v;
}
map<N,int> MM;
struct Node
{
    int ch[2],ff;
    int mm,val,rev; 
};
struct LCT
{
    struct Node t[MAX];
    void pushup(int x){t[x].mm=max(t[lson].mm,t[rson].mm);t[x].mm=max(t[x].mm,t[x].val);}
    bool isroot(int x){return t[fat].ch[0]!=x&&t[fat].ch[1]!=x;}
    void pushdown(int x)
    {
        if(!t[x].rev)return;
        swap(lson,rson);
        t[lson].rev^=1;t[rson].rev^=1;
        t[x].rev^=1;
    }
    void rotate(int x)
    {
        int y=t[x].ff,z=t[y].ff;
        int k=t[y].ch[1]==x;
        if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
        t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
        t[x].ch[k^1]=y;t[y].ff=x;   
        pushup(y);pushup(x);    
    }
    void Splay(int x)
    {
        S[top=1]=x;
        for(int i=x;!isroot(i);i=t[i].ff)S[++top]=t[i].ff;
        while(top)pushdown(S[top--]);
        while(!isroot(x))
        {
            int y=t[x].ff,z=t[y].ff;
            if(!isroot(y))
                (t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
            rotate(x);
        }
    }
    void access(int x){for(int y=0;x;y=x,x=t[x].ff)Splay(x),t[x].ch[1]=y,pushup(x);}
    void makeroot(int x){access(x);Splay(x);t[x].rev^=1;}
    void split(int x,int y){makeroot(x);access(y);Splay(y);}
    void cut(int x,int y){split(x,y);t[y].ch[0]=t[x].ff=0;}
    void link(int x,int y){makeroot(x);t[x].ff=y;}
    int findroot(int x){access(x);Splay(x);while(lson)x=lson;return x;}
}LCT[11];
int main()
{
    n=read();m=read();C=read();K=read();
    for(int i=1;i<=n;++i)val[i]=read();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=C;++j)
            LCT[j].t[i].val=val[i];
    for(int i=1,u,v,w;i<=m;++i)
    {
        u=read(),v=read(),w=read()+1;
        MM[(N){u,v}]=w;
        MM[(N){v,u}]=w;
        color[u][w]++;color[v][w]++;
        LCT[w].link(u,v);
    }
    while(K--)
    {
        int opt=read();
        if(opt==0)
        {
            int x=read();val[x]=read();
            for(int i=1;i<=C;++i)
            {
                LCT[i].access(x);
                LCT[i].Splay(x);
                LCT[i].t[x].val=val[x];
            }
        }
        else if(opt==1)
        {
            int u=read(),v=read(),w=read()+1;
            int G=MM[(N){u,v}];
            if(!G){puts("No such edge.");continue;}
            if(G==w){puts("Success.");continue;}
            if(color[u][w]>1||color[v][w]>1){puts("Error 1.");continue;}
            if(LCT[w].findroot(u)==LCT[w].findroot(v)){puts("Error 2.");continue;}
            color[u][w]++;color[v][w]++;
            color[u][G]--;color[v][G]--;
            MM[(N){u,v}]=w;MM[(N){v,u}]=w;
            LCT[G].cut(u,v);
            LCT[w].link(u,v);
            puts("Success.");
        }
        else
        {
            int w=read()+1,u=read(),v=read();
            if(LCT[w].findroot(u)!=LCT[w].findroot(v)){puts("-1");continue;}
            LCT[w].split(u,v);
            printf("%d\n",LCT[w].t[v].mm);
        }
    }
    return 0;
}

【BZOJ2816】【ZJOI2012】網絡(Link-Cut Tree)