给出一个 n n n个点 m m m条边的无向图,每个询问会让你删除一条 x , y x,y x,y的边
或者是询问你 x , y x,y x,y间路径最大值的最小值。
n , q ≤ 1 0 5 , m ≤ 1 0 6 , l i m i t : 2500 m s n,q\leq 10^5,m\leq10^6,limit:2500ms n,q≤105,m≤106,limit:2500ms
此题是加强版。LCT会不会被卡到挂啊?
但是我并没有写加强版(雾
sol:
实际上对于原版来说不同的是点的数量,也就是说你需要用个map之类的东西维护一下,
而不是直接套邻接矩阵。
对于删边我们把它变成加边,就成了增量生成树问题。
然后就是 L C T LCT LCT维护 M S T MST MST的板子题了:对于点 x , y x,y x,y用 L C T LCT LCT拉出路径上的最大值,
和当前新加的边比较一下是不是要断掉。
我们选择把边权转点权,方法是两个点拆成三个,中间一个虚点赋值。
数据结构题好久没有在没拍的情况下1A了。
#include
#include
#include
#define debug printf("GG\n")
const int N = 3e5 + 7;
int s[N], v[N];
inline int max(int a, int b) {return a > b ? a : b;}
inline int ckmax(int a, int b) {return v[a] > v[b] ? a : b;}
struct LCT {
int rev[N], w[N], f[N], ch[N][2], siz[N], mx[N];
#define lc ch[x][0]
#define rc ch[x][1]
#define sp(a, b) std :: swap(a, b)
inline int getwho(int x) {return ch[f[x]][0] == x ? 0 : 1;}
inline void pushup(int x) {mx[x] = ckmax(x, ckmax(mx[lc], mx[rc]));}
inline void resv(int x) {sp(lc, rc), rev[x] ^= 1;}
inline int nort(int x) {return ch[f[x]][0] == x || ch[f[x]][1] == x;}
inline void Rotate(int x) {
int fa = f[x], gra = f[f[x]], who = getwho(x);
if (nort(fa)) ch[gra][getwho(fa)] = x;
f[x] = gra;
ch[fa][who] = ch[x][who ^ 1], f[ch[x][who ^ 1]] = fa;
ch[x][who ^ 1] = fa, f[fa] = x;
pushup(fa), pushup(x);
}
inline void pushdown(int x) {
if (rev[x]) {
if (lc) resv(lc);
if (rc) resv(rc);
rev[x] = 0;
}
}
inline void splay(int x) {
int o = x, cnt = 0;
s[++cnt] = o;
while (nort(o)) s[++cnt] = (o = f[o]);
while (cnt) pushdown(s[cnt--]);
while (nort(x)) {
int fa = f[x];
if (nort(fa))
Rotate(getwho(fa) == getwho(x) ? fa : x);
Rotate(x);
}
}
inline void access(int x) {
for (int y = 0; x; y = x, x = f[x])
splay(x), rc = y, pushup(x);
}
inline void bert(int x) {access(x), splay(x), resv(x);}
inline int findrt(int x) {
access(x), splay(x);
while (lc) pushdown(x), x = lc;
splay(x);return x;
}
inline void split(int x, int y) {bert(x), access(y), splay(y);}
inline int link(int x, int y) {
bert(x);
if (findrt(y) == x) return 0;
f[x] = y; return 1;
}
inline int cut(int x, int y) {
bert(x);
if (findrt(y) != x || f[y] != x /*|| ch[x][0] != y*/) return 0;
f[y] = ch[x][1] = 0, pushup(x);
return 1;
}
}t; int n, m, Q, tot;
const int upNode = 3e3+7;
struct Edge {int from, to, id;} e[N*2];
int cNode[N][2], pcnt, map[upNode][upNode];
struct Question {int opt, x, y;} q[N*2];
int ff[N], size[N];
inline int find(int x) {
if (ff[x] == x) return x;
ff[x] = find(ff[x]);
return ff[x];
}
inline int Union(int x, int y) {
// debug;
int a = find(x), b = find(y);
if (a == b) return 0;
if (size[a] > size[b]) ff[b] = a;
else if (size[a] == size[b]) ff[b] = a, size[a]++;
else ff[a] = b;
return 1;
}
struct res {int st, to, w, id;} eres[N*2];
inline int cmp(res a, res b) {return a.w < b.w;}
int orgi[N*2];
void init() {
scanf("%d%d%d", &n, &m, &Q);
for (int i = 1; i <= 3e5; i++) ff[i] = i;
for (int i = 1; i <= m; i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
if (x > y) std :: swap(x, y);
eres[i].st = x, eres[i].to = y, eres[i].w = z;
e[++tot].from = x,
e[tot].to = i;
e[++tot].from = i,
e[tot].to = y;
v[i + n] = z;
cNode[i + n][0] = x, cNode[i + n][1] = y;
eres[i].id = i + n;
}
for (int i = 1; i <= Q; i++) {
scanf("%d%d%d", &q[i].opt, &q[i].x, &q[i].y);
if (q[i].x > q[i].y) std :: swap(q[i].x, q[i].y);
if (q[i].opt == 2) map[q[i].x][q[i].y] = 1;
}
std :: sort(eres + 1, eres + m + 1, cmp);
int ptot = 0;
for (int i = 1; i <= m; i++) {
int a = find(eres[i].st), b = find(eres[i].to);
if (a == b || map[eres[i].st][eres[i].to]) continue;
Union(a, b);
t.link(eres[i].st, eres[i].id), t.link(eres[i].id, eres[i].to);
ptot++;
if (ptot == n - 1) break;
}
for (int i = 1; i <= m; i++)
if (map[e[i * 2 - 1].from][e[i * 2].to])
map[e[i * 2 - 1].from][e[i * 2].to] = i + n;
} int stack[N]; int opts;
void solve() {
for (int i = Q; i >= 1; i--) {
if (q[i].opt == 2) {
//debug;
t.split(q[i].x, q[i].y);
// debug;
int o = t.mx[q[i].y];
if (v[o] > v[map[q[i].x][q[i].y]])
t.cut(cNode[o][0], o), t.cut(o, cNode[o][1]),
t.link(q[i].x, map[q[i].x][q[i].y]), t.link(map[q[i].x][q[i].y], q[i].y);
else continue;
} else {
// debug;
t.split(q[i].x, q[i].y);
stack[++opts] = v[t.mx[q[i].y]];
}
}
while (opts) printf ("%d\n", stack[opts--]);
}
int main() {
init();
//debug;
solve();
}