ZJOI2012网络 题解报告【LCT】
題目描述
有一個無向圖G,每個點有個權值,每條邊有一個顏色。這個無向圖滿足以下兩個條件:
對于任意節點連出去的邊中,相同顏色的邊不超過兩條。
在這個圖上,你要支持以下三種操作:
修改一個節點的權值。
修改一條邊的顏色。
輸入輸出格式
輸入格式:輸入文件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。
輸出文件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
說明
顏色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。
題解
題目拿來一看,路徑唯一,那么對于每種顏色就是一棵樹,而且是動態的樹,顏色改變就相當于斷邊與連邊 很自然就想到對于每種顏色各建一棵LCT 很方地往下看數據范圍。。。。nice√最多也就10種顏色,完全可以承受由于一個節點的邊最多兩條,可以將它存下來,每次修改顏色時暴力查找就好了,不用想太多。。 【修改顏色甚至有可能是原來的顏色= =,忽略這個就才20分。。。加上一句特判就A了。。。扯淡吧。。】
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define LL long long int #define isr(u,c) (e[c][e[c][u].f].ch[1] == u) #define isrt(u,c) (!e[c][u].f || (e[c][e[c][u].f].ch[0] != u && e[c][e[c][u].f].ch[1] != u)) using namespace std; const int maxn = 10005,maxm = 100005,INF = 200000000;inline int read(){int out = 0,flag = 1;char c = getchar();while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}while (c >= 48 && c <= 57) {out = out * 10 + c - 48; c = getchar();}return out * flag; }int N,M,C,K,temp[maxn]; int edge[maxn][11][3];struct node{int w,f,ch[2],rev,Max;node() {f = ch[0] = ch[1] = rev = 0;} }e[11][maxn];inline void push_up(int u,int c){e[c][u].Max = max(e[c][u].w,max(e[c][e[c][u].ch[0]].Max,e[c][e[c][u].ch[1]].Max)); }inline void pd(int u,int c){if (e[c][u].rev){swap(e[c][u].ch[0],e[c][u].ch[1]);e[c][e[c][u].ch[0]].rev ^= 1;e[c][e[c][u].ch[1]].rev ^= 1;e[c][u].rev = 0;} }inline void push_down(int u,int c){int i = 0;do {temp[++i] = u;} while(!isrt(u,c) && (u = e[c][u].f));while (i) pd(temp[i--],c); }inline int Find(int u,int c){while (e[c][u].f) u = e[c][u].f;return u; }inline void spin(int u,int c){int s = isr(u,c),fa = e[c][u].f;e[c][u].f = e[c][fa].f;if(!isrt(fa,c)) e[c][e[c][fa].f].ch[isr(fa,c)] = u;e[c][fa].ch[s] = e[c][u].ch[s^1];if(e[c][u].ch[s^1]) e[c][e[c][u].ch[s^1]].f = fa;e[c][fa].f = u;e[c][u].ch[s^1] = fa;push_up(fa,c); }inline void splay(int u,int c){push_down(u,c);while (!isrt(u,c)){if(isrt(e[c][u].f,c)) spin(u,c);else if(isr(u,c) ^ isr(e[c][u].f,c)) spin(u,c),spin(u,c);else spin(e[c][u].f,c),spin(u,c);}push_up(u,c); }inline void Access(int u,int c){for (int v = 0; u; u = e[c][v = u].f){splay(u,c);e[c][u].ch[1] = v;if (v) e[c][v].f = u;push_up(u,c);} }inline void Make_root(int u,int c){Access(u,c); splay(u,c);e[c][u].rev ^= 1; }inline bool Link(int u,int v,int c){if(Find(u,c) == Find(v,c)){printf("Error 2.\n");return false;}Make_root(u,c); Access(v,c); splay(v,c);e[c][u].f = v;return true; }inline void Cut(int u,int v,int c){Make_root(u,c); Access(v,c); splay(v,c);e[c][v].ch[0] = 0;e[c][u].f = 0;push_up(v,c); }inline void Change(int u,int w){for (int i = 0; i < C; i++){Access(u,i); splay(u,i);e[i][u].w = w;push_up(u,i);} }inline int Query(int u,int v,int c){if(Find(u,c) != Find(v,c)) return -1;Make_root(u,c); Access(v,c); splay(v,c);return e[c][v].Max; }void init(){for (int i = 0; i <= 10; i++) e[i][0].Max = -INF;N = read();M = read();C = read();K = read();int u,v,w;for (int i = 1; i <= N; i++){w = read();for (int j = 0; j < C; j++)e[j][i].w = e[j][i].Max = w;}while (M--){u = read();v = read();w = read();Link(u,v,w);edge[u][w][++edge[u][w][0]] = v;edge[v][w][++edge[v][w][0]] = u;} }void solve(){int k,x,y,z,c;while (K--){k = read();if (k == 0){x = read(); y = read();Change(x,y);}else if (k == 1){x = read(); y = read(); z = read();c = -1;for (int i = 0; i < C; i++)for (int j = 1; j <= edge[x][i][0]; j++)if (edge[x][i][j] == y){c = i;if (edge[x][i][0] == 2 && j == 1) swap(edge[x][i][1],edge[x][i][2]);if (edge[y][i][0] == 2 && edge[y][i][1] == x) swap(edge[y][i][1],edge[y][i][2]);break;}if (c == -1) printf("No such edge.\n");else if(c == z) printf("Success.\n");else if(edge[x][z][0] == 2 || edge[y][z][0] == 2) printf("Error 1.\n");else{if (Link(x,y,z)){edge[x][c][0]--;edge[y][c][0]--;edge[x][z][++edge[x][z][0]] = y;edge[y][z][++edge[y][z][0]] = x;Cut(x,y,c);printf("Success.\n");}}}else{c = read(); x = read(); y = read();printf("%d\n",Query(x,y,c));}} }int main() {init();solve();return 0; }
轉載于:https://www.cnblogs.com/Mychael/p/8282868.html
總結
以上是生活随笔為你收集整理的ZJOI2012网络 题解报告【LCT】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: unity---------------
- 下一篇: [不定期更新]需要记住的结论