有一個無向圖G,每一個點有個權值,每條邊有一個顏色。這個無向圖知足如下兩個條件:node
在這個圖上,你要支持如下三種操做:c++
輸入文件network.in的第一行包含四個正整數N, M, C, K,其中N爲節點個數,M爲邊數,C爲邊的顏色數,K爲操做數。git
接下來N行,每行一個正整數vi,爲節點i的權值。this
以後M行,每行三個正整數u, v, w,爲一條鏈接節點u和節點v的邊,顏色爲w。知足1 ≤ u, v ≤ N,0 ≤ w < C,保證u ≠ v,且任意兩個節點之間最多存在一條邊(不管顏色)。spa
最後K行,每行表示一個操做。每行的第一個整數k表示操做類型。code
輸出文件network.out包含若干行,每行輸出一個對應的信息。blog
a) 若不存在鏈接節點u和節點v的邊,輸出「No such edge.」。get
b) 若修改後不知足條件1,不修改邊的顏色,並輸出「Error 1.」。it
c) 若修改後不知足條件2,不修改邊的顏色,並輸出「Error 2.」。class
d) 其餘狀況,成功修改邊的顏色,並輸出「Success.」。
輸出知足條件的第一條信息便可,即若同時知足b和c,則只須要輸出「Error 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
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。
#include<bits/stdc++.h> #define LL long long LL in() { char ch; LL x = 0, f = 1; while(!isdigit(ch = getchar()))(ch == '-') && (f = -f); for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48)); return x * f; } using std::map; using std::pair; using std::make_pair; const int maxn = 1e4 + 10; struct LCT { protected: struct node { node *ch[2], *fa; int val, max, rev; node(int val = 0, int max = 0, int rev = 0): val(val), max(max), rev(rev) { ch[0] = ch[1] = fa = NULL; } void trn() { std::swap(ch[0], ch[1]), rev ^= 1; } void upd() { max = val; if(ch[0]) max = std::max(max, ch[0]->max); if(ch[1]) max = std::max(max, ch[1]->max); } void dwn() { if(!rev) return; if(ch[0]) ch[0]->trn(); if(ch[1]) ch[1]->trn(); rev = 0; } bool ntr() { return fa && (fa->ch[0] == this || fa->ch[1] == this); } bool isr() { return this == fa->ch[1]; } }pool[maxn]; void rot(node *x) { node *y = x->fa, *z = y->fa; bool k = x->isr(); node *w = x->ch[!k]; if(y->ntr()) z->ch[y->isr()] = x; x->ch[!k] = y, y->ch[k] = w; y->fa = x, x->fa = z; if(w) w->fa = y; y->upd(), x->upd(); } void splay(node *o) { static node *st[maxn]; int top; st[top = 1] = o; while(st[top]->ntr()) st[top + 1] = st[top]->fa, top++; while(top) st[top--]->dwn(); while(o->ntr()) { if(o->fa->ntr()) rot(o->isr() ^ o->fa->isr()? o : o->fa); rot(o); } } void access(node *x) { for(node *y = NULL; x; x = (y = x)->fa) splay(x), x->ch[1] = y, x->upd(); } void makeroot(node *x) { access(x), splay(x), x->trn(); } node *findroot(node *x) { access(x), splay(x); while(x->dwn(), x->ch[0]) x = x->ch[0]; return x; } public: void init(int id, int val) { pool[id].val = val, pool[id].upd(); } void link(int l, int r) { node *x = pool + l, *y = pool + r; makeroot(x), x->fa = y; } void cut(int l, int r) { node *x = pool + l, *y = pool + r; makeroot(x), access(y), splay(y); if(y->ch[0] == x) y->ch[0] = x->fa = NULL; } void change(int pos, int k) { node *o = pool + pos; splay(o); o->val = k, o->upd(); } bool judge(int x, int y) { return findroot(pool + x) == findroot(pool + y); } int query(int l, int r) { if(!judge(l, r)) return -1; node *x = pool + l, *y = pool + r; makeroot(x), access(y), splay(y); return y->max; } }s[10]; int n, m, c, k; map<pair<int, int>, int> mp; int num[maxn][12]; int main() { n = in(), m = in(), c = in(), k = in(); for(int i = 1; i <= n; i++) { int val = in(); for(int j = 0; j < c; j++) s[j].init(i, val); } int p, x, y, v; for(int i = 1; i <= m; i++) { x = in(), y = in(), v = in(); if(x > y) std::swap(x, y); mp[make_pair(x, y)] = v + 1; s[v].link(x, y); num[x][v]++, num[y][v]++; } while(k --> 0) { p = in(); if(p == 0) { x = in(), y = in(); for(int i = 0; i < c; i++) s[i].change(x, y); } if(p == 1) { x = in(), y = in(), v = in(); if(x > y) std::swap(x, y); if(!mp.count(make_pair(x, y))) { printf("No such edge.\n"); continue; } if(mp[make_pair(x, y)] - 1 != v && (num[x][v] > 1 || num[y][v] > 1)) { printf("Error 1.\n"); continue; } if(mp[make_pair(x, y)] - 1 != v && s[v].judge(x, y)) { printf("Error 2.\n"); continue; } num[x][mp[make_pair(x, y)] - 1]--, num[y][mp[make_pair(x, y)] - 1]--; num[x][v]++, num[y][v]++; s[mp[make_pair(x, y)] - 1].cut(x, y); mp[make_pair(x, y)] = v + 1; s[v].link(x, y); printf("Success.\n"); } if(p == 2) v = in(), x = in(), y = in(), printf("%d\n", s[v].query(x, y)); } return 0; }