bzoj2594 [Wc2006]水管局长数据加强版
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2594
【题解】
不难考虑到这样一个性质:u->v路径上最大边最小,一定在MST上。
这个可以用kruskal来证明
有了这个结论就这题很显然就可做了。
考虑时光倒流,变成加边、询问u->v路径上最大边最小值。
可以用LCT维护边权最大值以及出现位置,即可。
复杂度$O(nlog(n+m))$。
竟然1A了。。还刚好25s。感觉非常优秀。
竟然只写了20min,代码可读性很高
# include <map> # include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 1.5e6 + 10, N = 1e5 + 10; const int mod = 1e9+7; // 性质:u->v路径上最大边最小,一定在MST上。 int n, m, ans[N]; bool v[M]; map<int, int> mp[N]; inline int getint() { char ch = getchar(); int x = 0; while(!isdigit(ch)) ch = getchar(); while(isdigit(ch)) x = (x<<3) + (x<<1) + ch - '0', ch = getchar(); return x; } struct pa { int t, a, b; pa() {} pa(int t, int a, int b) : t(t), a(a), b(b) {} }q[N]; struct edge { int u, v, t; edge() {} edge(int u, int v, int t) : u(u), v(v), t(t) {} friend bool operator < (edge a, edge b) { return a.t < b.t; } }e[M]; struct us { int fa[N], n; inline void set(int _n) { n = _n; for (int i=1; i<=n; ++i) fa[i] = i; } inline int getf(int x) { return fa[x] == x ? x : fa[x] = getf(fa[x]); } inline void un(int fx, int fy) { fa[fx] = fy; } }U; struct LCT { int ch[M][2], fa[M], val[M], mx[M], id[M]; bool rev[M]; inline void set() { memset(ch, 0, sizeof ch); memset(fa, 0, sizeof fa); memset(val, 0, sizeof val); memset(mx, 0, sizeof mx); memset(rev, 0, sizeof rev); memset(id, 0, sizeof id); } # define ls ch[x][0] # define rs ch[x][1] inline void up(int x) { if(!x) return ; mx[x] = val[x]; id[x] = x; if(mx[x] < mx[ls]) mx[x] = mx[ls], id[x] = id[ls]; if(mx[x] < mx[rs]) mx[x] = mx[rs], id[x] = id[rs]; } inline void pushrev(int x) { if(!x) return ; swap(ls, rs); rev[x] ^= 1; } inline void down(int x) { if(!x || !rev[x]) return ; pushrev(ls), pushrev(rs); rev[x] = 0; } # undef ls # undef rs inline bool isrt(int x) { return ch[fa[x]][0] != x && ch[fa[x]][1] != x; } inline void rotate(int x) { int y = fa[x], z = fa[y], ls = ch[y][1] == x, rs = ls^1; if(!isrt(y)) ch[z][ch[z][1] == y] = x; fa[ch[x][rs]] = y, fa[y] = x, fa[x] = z; ch[y][ls] = ch[x][rs]; ch[x][rs] = y; up(y); up(x); } int st[M]; inline void splay(int x) { int stn = 0, tx = x; while(!isrt(tx)) st[++stn] = tx, tx = fa[tx]; st[++stn] = tx; for (int i=stn; i; --i) down(st[i]); while(!isrt(x)) { int y = fa[x], z = fa[y]; if(!isrt(y)) { if((ch[y][0] == x) ^ (ch[z][0] == y)) rotate(x); else rotate(y); } rotate(x); } } inline int access(int x) { int t = 0; for (; x; t = x, x = fa[x]) { splay(x); ch[x][1] = t; up(x); } return t; } inline void makeroot(int x) { access(x); splay(x); pushrev(x); } inline void link(int x, int y) { makeroot(x); fa[x] = y; } inline int cut(int x, int y) { makeroot(x); access(y); splay(y); ch[y][0] = fa[x] = 0; up(y); } inline int split(int x, int y) { makeroot(x); access(y); splay(y); return y; } }T; int main() { n = getint(), m = getint(); int Q = getint(); U.set(n); T.set(); for (int i=1; i<=m; ++i) e[i].u = getint(), e[i].v = getint(), e[i].t = getint(); sort(e+1, e+m+1); for (int i=1; i<=m; ++i) mp[e[i].u][e[i].v] = i, mp[e[i].v][e[i].u] = i; for (int i=1; i<=Q; ++i) { q[i].t = getint(); q[i].a = getint(), q[i].b = getint(); if(q[i].t == 2) v[mp[q[i].a][q[i].b]] = 1; } for (int i=1, x; i<=m; ++i) { if(v[i]) continue; int fu = U.getf(e[i].u), fv = U.getf(e[i].v); if(fu != fv) { x = i+n; U.un(fu, fv); T.val[x] = e[i].t; T.link(e[i].u, x); T.link(e[i].v, x); } } for (int i=Q, x, t, y; i; --i) { x = T.split(q[i].a, q[i].b); if(q[i].t == 1) ans[i] = T.mx[x]; else { // adde (q[i].a, q[i].b) y = n + mp[q[i].a][q[i].b]; t = e[y-n].t; if(t < T.mx[x]) { T.val[y] = t; t = T.id[x]; T.cut(t, e[t-n].u); T.cut(t, e[t-n].v); T.link(q[i].a, y); T.link(q[i].b, y); } } } for (int i=1; i<=Q; ++i) if(q[i].t == 1) printf("%d\n", ans[i]); return 0; }