[WC 2006] 水管局长
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=2594
[算法]
首先离线 , 将删边操作转化为倒序加边
假设我们已经维护出了一棵最小生成树T , 若加入了一条边(u , v , w) , 那么形成了一个环 ,考虑kruskal算法的执行过程 :
若w < 环上的边权最大值 , 那么可以将(u , v , w)加入 , 并将环上边权最大的边删除
可以使用LCT维护
时间复杂度 : O(NlogN ^ 2) , 注意常数优化
[代码]
#include<bits/stdc++.h> using namespace std; const int MAXN = 3e5 + 10; typedef long long ll; typedef long double ld; typedef unsigned long long ull; struct edge { int u , v , w; } e[MAXN << 1]; struct query { int type; int u , v; } que[MAXN << 1]; int n , m , q; int fa[MAXN]; bool flg[MAXN]; struct Link_Cut_Tree { struct Node { int father , son[2] , mx , value , id; bool tag; } a[MAXN << 2]; inline void update(int x) { a[x].mx = a[x].value; a[x].id = x; if (a[x].son[0]) { if (a[a[x].son[0]].mx > a[x].mx) { a[x].mx = a[a[x].son[0]].mx; a[x].id = a[a[x].son[0]].id; } } if (a[x].son[1]) { if (a[a[x].son[1]].mx > a[x].mx) { a[x].mx = a[a[x].son[1]].mx; a[x].id = a[a[x].son[1]].id; } } } inline void init() { for (int i = n + 1; i <= n + m + 1; i++) { a[i].mx = a[i].value = e[i - n].w; a[i].id = i; } } inline void pushdown(int x) { if (a[x].tag) { swap(a[x].son[0] , a[x].son[1]); a[a[x].son[0]].tag ^= 1; a[a[x].son[1]].tag ^= 1; a[x].tag = false; } } inline bool get(int x) { pushdown(a[x].father); return a[a[x].father].son[1] == x; } inline bool nroot(int x) { return a[a[x].father].son[0] == x | a[a[x].father].son[1] == x; } inline void rotate(int x) { int f = a[x].father , g = a[f].father; int tmpx = get(x) , tmpf = get(f); int w = a[x].son[tmpx ^ 1]; if (nroot(f)) a[g].son[tmpf] = x; a[x].son[tmpx ^ 1] = f; a[f].son[tmpx] = w; if (w) a[w].father = f; a[f].father = x; a[x].father = g; update(f); } inline int find_root(int x) { access(x); splay(x); while (a[x].son[0]) { pushdown(x); x = a[x].son[0]; } return x; } inline void access(int x) { for (int y = 0; x; x = a[y = x].father) { splay(x); a[x].son[1] = y; update(x); } } inline void splay(int x) { int y = x , z = 0; static int st[MAXN]; st[++z] = y; while (nroot(y)) st[++z] = y = a[y].father; while (z) pushdown(st[z--]); while (nroot(x)) { int y = a[x].father , z = a[y].father; if (nroot(y)) rotate((a[y].son[0] == x) ^ (a[z].son[0] == y) ? x : y); rotate(x); } update(x); } inline void split(int x , int y) { make_root(x); access(y); splay(y); } inline void make_root(int x) { access(x); splay(x); a[x].tag ^= true; pushdown(x); } inline void link(int x , int y) { make_root(x); if (find_root(y) != x) a[x].father = y; } inline void cut(int x , int y) { make_root(x); if (find_root(y) == x && a[x].father == y && !a[x].son[1]) { a[x].father = a[y].son[0] = 0; update(y); } } inline int query(int x) { return a[x].id; } } LCT; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline bool cmp(edge a , edge b) { return a.w < b.w; } inline int get_root(int x) { if (fa[x] == x) return x; else return fa[x] = get_root(fa[x]); } int main() { read(n); read(m); read(q); for (int i = 1; i <= m; i++) { read(e[i].u); read(e[i].v); read(e[i].w); if (e[i].u > e[i].v) swap(e[i].u , e[i].v); } sort(e + 1 , e + m + 1 , cmp); map< pair<int , int> , int> mp; for (int i = 1; i <= m; i++) mp[make_pair(e[i].u , e[i].v)] = i; for (int i = 1; i <= q; i++) { read(que[i].type); read(que[i].u); read(que[i].v); if (que[i].u > que[i].v) swap(que[i].u , que[i].v); if (que[i].type == 2) flg[mp[make_pair(que[i].u , que[i].v)]] = true; } LCT.init(); for (int i = 1; i <= n; i++) fa[i] = i; for (int i = 1; i <= m; i++) { if (flg[i]) continue; int su = get_root(e[i].u) , sv = get_root(e[i].v); if (su != sv) { fa[su] = sv; LCT.link(e[i].u , i + n); LCT.link(e[i].v , i + n); } } vector< int > ans; for (int i = q; i >= 1; i--) { if (que[i].type == 1) { LCT.split(que[i].u , que[i].v); ans.push_back(e[LCT.query(que[i].v) - n].w); } else { LCT.split(que[i].u , que[i].v); int id = LCT.query(que[i].v); if (e[mp[make_pair(que[i].u , que[i].v)]].w < e[id - n].w) { LCT.cut(e[id - n].u , id); LCT.cut(e[id - n].v , id); LCT.link(que[i].u , mp[make_pair(que[i].u , que[i].v)] + n); LCT.link(que[i].v , mp[make_pair(que[i].u , que[i].v)] + n); } } } reverse(ans.begin() , ans.end()); for (unsigned i = 0; i < ans.size(); i++) printf("%d\n" , ans[i]); return 0; }