[ZJOI2012]網絡

題目描述

有一個無向圖G,每一個點有個權值,每條邊有一個顏色。這個無向圖知足如下兩個條件:node

  1. 對於任意節點連出去的邊中,相同顏色的邊不超過兩條。ios

  2. 圖中不存在同色的環,同色的環指相同顏色的邊構成的環。

在這個圖上,你要支持如下三種操做:數組

  1. 修改一個節點的權值。spa

  2. 修改一條邊的顏色。code

  3. 查詢由顏色c的邊構成的圖中,全部可能在節點u到節點v之間的簡單路徑上的節點的權值的最大值。

輸入輸出格式

輸入格式:blog

輸入文件network.in的第一行包含四個正整數N, M, C, K,其中N爲節點個數,M爲邊數,C爲邊的顏色數,K爲操做數。get

接下來N行,每行一個正整數vi,爲節點i的權值。string

以後M行,每行三個正整數u, v, w,爲一條鏈接節點u和節點v的邊,顏色爲w。知足1 ≤ u, v ≤ N,0 ≤ w < C,保證u ≠ v,且任意兩個節點之間最多存在一條邊(不管顏色)。it

最後K行,每行表示一個操做。每行的第一個整數k表示操做類型。io

  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

說明

顏色0爲實線的邊,顏色1爲虛線的邊,

由顏色0構成的從節點1到節點4的路徑有1 – 2 – 4,故max{v1, v2, v4} = max{ 1, 2, 4 } = 4。

將鏈接節點1和節點2的邊修改成顏色1,修改爲功,輸出「Success.」

將鏈接節點4和節點3的邊修改成顏色1,因爲修改後會使得存在由顏色1構成的環( 1 – 2 – 4 – 3 – 1 ),不知足條件2,故不修改,並輸出「Error 2」。

不存在顏色0構成的從節點1到節點4的邊,輸出「-1」。

將鏈接節點2和節點3的邊修改成顏色1,因爲修改後節點2的連出去的顏色爲1的邊有3條,故不知足條件1,故不修改,並輸出「Error 1.」。

將節點2的權值修改成5。

由顏色1構成的從節點1到節點4的路徑有 1 – 2 – 4,故max{v1, v2, v4} = max{ 1, 5, 4 } = 5。

【數據規模】

對於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,果斷開10棵LCT。

  1.對於操做1,在每個LCT中修改這個點的點權就好。

  2.對於操做2,個人方法是用一個鏈表來存邊,若是a和b之間沒有邊,就輸出「No such edge」。用一個數組in來存出度,若是出度>2而且顏色改變,就輸出「Error 2.」。而後判斷一下這兩個點是否聯通,若是聯通且不是直接聯通,就輸出「Error 2.」。其餘狀況直接link就好。

  1 //Never forget why you start
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<cmath>
  7 #include<algorithm>
  8 #define ll(x) lct[x].child[0]
  9 #define rr(x) lct[x].child[1]
 10 #define son(x,t) lct[x].child[t]
 11 using namespace std;
 12 int n,m,C,k;
 13 int in[10005][10];
 14 struct Tree{
 15   struct LCT{
 16     int child[2],fa,size,x,mmax,rev;
 17     bool is_root;
 18   }lct[10005];
 19   void push_up(int x){
 20     lct[x].size=lct[ll(x)].size+lct[rr(x)].size+1;
 21     lct[x].mmax=max(lct[x].x,max(lct[ll(x)].mmax,lct[rr(x)].mmax));
 22   }
 23   void push_rev(int x){
 24     if(!x)return;
 25     swap(ll(x),rr(x));
 26     lct[x].rev^=1;
 27   }
 28   void push_down(int x){
 29     if(lct[x].rev){
 30       push_rev(ll(x));
 31       push_rev(rr(x));
 32       lct[x].rev^=1;
 33     }
 34   }
 35   void push(int x){
 36     if(!lct[x].is_root)push(lct[x].fa);
 37     push_down(x);
 38   }
 39   int getson(int x){
 40     return x==son(lct[x].fa,1);
 41   }
 42   void rotate(int x){
 43     if(lct[x].is_root)return;
 44     int fa=lct[x].fa,fafa=lct[fa].fa,t=getson(x);
 45     son(fa,t)=son(x,!t);if(son(x,!t))lct[son(x,!t)].fa=fa;
 46     lct[fa].fa=x;son(x,!t)=fa;
 47     lct[x].fa=fafa;
 48     if(!lct[fa].is_root)son(fafa,son(fafa,1)==fa)=x;
 49     else lct[x].is_root=1,lct[fa].is_root=0;
 50     push_up(fa);
 51     push_up(x);
 52   }
 53   void splay(int x){
 54     push(x);
 55     for(int fa;!lct[x].is_root;rotate(x))
 56       if(!lct[fa=lct[x].fa].is_root)
 57     rotate(getson(fa)==getson(x)?fa:x);
 58   }
 59   void access(int x){
 60     int y=0;
 61     do{
 62       splay(x);
 63       lct[rr(x)].is_root=1;
 64       lct[rr(x)=y].is_root=0;
 65       push_up(x);
 66       x=lct[y=x].fa;
 67     }while(x);
 68   }
 69   void mroot(int x){
 70     access(x);
 71     splay(x);
 72     push_rev(x);
 73   }
 74   void link(int u,int v){
 75     mroot(u);
 76     lct[u].fa=v;
 77   }
 78   void cut(int u,int v){
 79     mroot(u);
 80     access(v);splay(v);
 81     lct[ll(v)].fa=lct[v].fa;
 82     lct[ll(v)].is_root=1;
 83     ll(v)=lct[v].fa=0;
 84     push_up(v);
 85   }
 86   void change(int x,int y){
 87     mroot(x);
 88     lct[x].x=y;
 89     push_up(x);
 90   }//修改點
 91   bool judge(int x,int y){
 92     access(x);splay(x);while(ll(x))x=ll(x);
 93     access(y);splay(y);while(ll(y))y=ll(y);
 94     return x==y;
 95   }
 96   bool pd(int x,int y){
 97     mroot(x);
 98     access(y);splay(y);
 99     return (ll(y)==x)&&lct[ll(y)].size==1;
100   }
101   int query(int x,int y){
102     mroot(x);
103     access(y);splay(y);
104     return lct[y].mmax;
105   }
106 }T[10];
107 struct node{
108   int next,to,dis;
109 }edge[200005];
110 int head[10005],size=-1;
111 void putin(int from,int to,int dis){
112   size++;
113   edge[size].next=head[from];
114   edge[size].to=to;
115   edge[size].dis=dis;
116   head[from]=size;
117 }
118 int main(){
119   int i,j;
120   memset(head,-1,sizeof(head));
121   scanf("%d%d%d%d",&n,&m,&C,&k);
122   for(i=1;i<=n;i++){
123     int x;scanf("%d",&x);
124     for(j=0;j<C;j++){
125       T[j].lct[i].size=T[j].lct[i].is_root=1;
126       T[j].lct[i].x=T[j].lct[i].mmax=x;
127     }
128   }
129   for(i=1;i<=m;i++){
130     int u,v,c;
131     scanf("%d%d%d",&u,&v,&c);
132     putin(u,v,c);
133     putin(v,u,c);
134     in[u][c]++;
135     in[v][c]++;
136     T[c].link(u,v);
137   }
138   for(i=1;i<=k;i++){
139     int a,b,c,d;
140     scanf("%d%d%d",&d,&a,&b);
141     if(d==0){
142       
143       for(j=0;j<C;j++)
144     T[j].change(a,b);
145       
146     }
147     else if(d==1){
148       
149       scanf("%d",&c);
150       
151       bool flag=0;
152       for(j=head[a];j!=-1;j=edge[j].next)if(edge[j].to==b){flag=1;break;}
153       if(!flag){printf("No such edge.\n");continue;}
154       
155       int last=edge[j].dis;
156       if((in[a][c]==2&&last!=c)||(in[b][c]==2&&last!=c)){printf("Error 1.\n");continue;}
157 
158       if(T[c].judge(a,b)&&(!T[c].pd(a,b))){printf("Error 2.\n");continue;}
159       
160       in[a][last]--;in[b][last]--;
161       in[a][c]++;in[b][c]++;
162       edge[j].dis=c;edge[j^1].dis=c;
163       T[last].cut(a,b);
164       T[c].link(a,b);
165       printf("Success.\n");
166       
167     }
168     else if(d==2){
169       
170       scanf("%d",&c);
171       
172       if(!T[a].judge(b,c))printf("-1\n");
173       else printf("%d\n",T[a].query(b,c));
174       
175     }
176   }
177   return 0;
178 }
相關文章
相關標籤/搜索