【LCT】网络(luogu 2173/ZJOI2011)
生活随笔
收集整理的這篇文章主要介紹了
【LCT】网络(luogu 2173/ZJOI2011)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
正題
luogu 2173
題目大意
給你一個圖,每條邊有有一種顏色(numcolor?10num_{color}\leqslant 10numcolor??10),保證以下性質:
1.一個點連出的同色邊數(shù)不大于2
2.不存在同色邊組成的環(huán)
現(xiàn)在讓你進行3鐘操作:
1.修改一個點的權值
2.把兩個點的連邊換色(如果不存在這條邊,或修改后違背上文的性質,那么不修改)
3.輸出某一顏色中,一條路徑上的最大值
解題思路
如果只有單顏色,那么可以用LCT維護一棵樹,所有操作都可以在LCT上進行
因為numcolor?10num_{color}\leqslant 10numcolor??10,所以多顏色建多幾棵LCT即可
代碼
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define N 10100 using namespace std; int n, m, q, x, y, z, p, cn; struct LCT {int v[N], s[N], p[N], fa[N], deg[N], son[N][2];#define ls son[x][0]#define rs son[x][1]bool NR(int x){return fa[x] && (son[fa[x]][0] == x || son[fa[x]][1] == x);}bool IRS(int x){return son[fa[x]][1] == x;}void push_up(int x){s[x] = max(v[x], max(s[ls], s[rs]));return;}void pushr(int x){swap(ls, rs);p[x] ^= 1;return;}void push_down(int x){if (p[x]){if (ls) pushr(ls);if (rs) pushr(rs);p[x] = 0;}return;}void push_hall(int x){if (NR(x)) push_hall(fa[x]);push_down(x);return;}void rotate(int x){int y = fa[x], z = fa[y], k = IRS(x), g = son[x][!k];if (NR(y)) son[z][IRS(y)] = x;if (g) fa[g] = y;fa[x] = z;fa[y] = x;son[x][!k] = y;son[y][k] = g;push_up(y);return;}void Splay(int x){push_hall(x);while(NR(x)){if (NR(fa[x])){if (IRS(x) == IRS(fa[x])) rotate(fa[x]);else rotate(x);}rotate(x);}push_up(x);return;}void access(int x){for (int y = 0; x; y = x, x = fa[x])Splay(x), rs = y, push_up(x);}void make_root(int x){access(x);Splay(x);pushr(x);return;}int find_root(int x){access(x);Splay(x);while(ls) push_down(x), x = ls;Splay(x);return x;}void Split(int x, int y){make_root(x);access(y);Splay(y);return;}void link(int x, int y){deg[x]++;deg[y]++;make_root(x);if (find_root(y) != x) fa[x] = y;return;}bool cut(int x, int y){make_root(x);if (find_root(y) == x && fa[y] == x && !son[y][0]){deg[x]--;deg[y]--;fa[y] = son[x][1] = 0;push_up(x);return true;}return false;} }T[15];//建多棵樹 int main() {scanf("%d%d%d%d", &n, &m, &cn, &q);for (int i = 1; i <= n; ++i){scanf("%d", &T[0].v[i]);for (int j = 1; j < cn; ++j)T[j].v[i] = T[0].v[i];}for (int i = 1; i <= m; ++i){scanf("%d%d%d", &x, &y, &z);T[z].link(x, y);}while(q--){scanf("%d", &x);if (x == 0){scanf("%d%d", &x, &y);for (int i = 0; i <= cn; ++i)//每種顏色的樹都要修改{T[i].Splay(x);T[i].v[x] = y;T[i].push_up(x);}}else if (x == 1){scanf("%d%d%d", &x, &y, &z);p = -1;for (int i = 0; i < cn; ++i){if (T[i].cut(x, y))//看是否有這樣一條邊,如果有就先割掉{p = i;break;}}if (p == -1)//沒有連邊{puts("No such edge.");continue;}if (T[z].deg[x] == 2 || T[z].deg[y] == 2)//超度數(shù){T[p].link(x, y);//連回去puts("Error 1.");continue;}T[z].make_root(x);if (T[z].find_root(y) == x)//已經連通了,再連就會產生環(huán){T[p].link(x, y);puts("Error 2.");continue;}T[z].link(x, y);puts("Success.");}else if (x == 2){scanf("%d%d%d", &z, &x, &y);T[z].make_root(x);if (T[z].find_root(y) != x) puts("-1");else printf("%d\n", T[z].s[x]);}}return 0; }總結
以上是生活随笔為你收集整理的【LCT】网络(luogu 2173/ZJOI2011)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【倍增】【线段树】雨林跳跃(luogu
- 下一篇: 英文qq名字大全