PANDORA PARADOXXX

maniubi發表於2024-09-09

PANDORA PARADOXXX

題意

給出一棵樹,每次操作刪除樹上的一條邊,詢問樹上所有連通塊中直徑的最大值。

思路

倒序操作,刪邊變為連邊。

預處理出做完所有操作後的答案。

使用並查集維護連通性,記錄每個連通塊內直徑的端點。

合併兩個集合時,新的直徑端點只可能是原來兩個集合四個端點中的兩個。

使用 LCA 求樹上距離,列舉 \(6\) 種情況, 取最大即可。

最後正序輸出答案。

程式碼

#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
typedef long long ll;
template <typename T> void qr(T& x) {
	x = 0; T f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {if (ch == '-') f = -f;ch = getchar();}
    while (ch >= '0' && ch <= '9') {x = x * 10 + ch - 48;ch = getchar();}
    x *= f;
}
template <typename T> void qf(T x) {
	if (x < 0) putchar('-'), x = -x;
	if (x >= 10) qf(x / 10);
	putchar(x % 10 + 48);
}
int T, tot, ver[N << 1], nxt[N << 1], head[N];
int n, Q, u[N], v[N], q[N], fa[N][25], de[N];
ll d[N], w[N], edge[N], D[N], ans[N];
int f[N], P[N][2], mx, mxp;
bool qed[N], vis[N];
vector <pair<int,ll> > e[N];
void add(int x, int y, ll z) {
    ver[++ tot] = y;
    nxt[tot] = head[x];
    head[x] = tot;
    edge[tot] = z;
}
int find(int x) {return f[x] == x ? x : f[x] = find(f[x]);}
void link(int x, int y) {
    int fx = find(x), fy = find(y);
    if (fx == fy) return ;
    f[fx] = fy;
}
void init(int x) {
    de[x] = de[fa[x][0]] + 1;
    for (int i = 1; i < 25; i ++) 
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
    for (int i = head[x], y; i; i = nxt[i]) {
        y = ver[i];
        if (y == fa[x][0]) continue;
        fa[y][0] = x, d[y] = d[x] + edge[i];
        init(y);
    }
} 
int LCA(int x, int y) {
    if (de[x] < de[y]) swap(x, y);
    for (int i = 24; i >= 0; i --) 
        if (de[fa[x][i]] >= de[y]) x = fa[x][i];
    if (x == y) return x;
    for (int i = 24; i >= 0; i --)
        if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
    return fa[x][0];
}
ll dis(int x, int y) {return d[x] + d[y] - (d[LCA(x, y)] << 1);}
void dfs(int x) {
    if (D[x] > mx) mx = D[x], mxp = x;
    for (auto [y,w] : e[x]) {
        if (vis[y]) continue;
        vis[y] = 1, D[y] = D[x] + w;
        dfs(y);
        D[y] = vis[y] = 0;
    }
}
void solve() {
    qr(n), qr(Q);
    for (int i = 1; i < n; i ++) {
        qr(u[i]), qr(v[i]), qr(w[i]);
        add(u[i], v[i], w[i]), add(v[i], u[i], w[i]);
    }
    for (int i = 1; i <= n; i ++) f[i] = i;
    for (int i = 1; i <= Q; i ++) qr(q[i]), qed[q[i]] = 1;
    for (int i = 1; i < n; i ++) {
        if (qed[i]) continue;
        e[u[i]].push_back({v[i],w[i]});
        e[v[i]].push_back({u[i],w[i]});
        link(u[i], v[i]);
    }
    init(1);
    for (int i = 1; i <= n; i ++) {
        if (f[i] == i) {
            mx = -1;
            vis[i] = 1; dfs(i); vis[i] = 0;
            P[i][0] = mxp;
            mx = -1;
            vis[P[i][0]] = 1, dfs(P[i][0]); vis[P[i][0]] = 0;
            P[i][1] = mxp;
            ans[Q] = max(ans[Q], dis(P[i][0], P[i][1]));  
        }
    }
    for (int i = Q, fu, fv, nl, nr; i >= 1; i --) {
        fu = find(u[q[i]]), fv = find(v[q[i]]);
        ll p = dis(P[fu][0], P[fu][1]), nd = -1;
        if (p > nd) nd = p, nl = P[fu][0], nr = P[fu][1];
        p = dis(P[fv][0], P[fv][1]);
        if (p > nd) nd = p, nl = P[fv][0], nr = P[fv][1];
        p = dis(P[fu][0], P[fv][0]);
        if (p > nd) nd = p, nl = P[fu][0], nr = P[fv][0];
        p = dis(P[fu][0], P[fv][1]);
        if (p > nd) nd = p, nl = P[fu][0], nr = P[fv][1];
        p = dis(P[fu][1], P[fv][0]);
        if (p > nd) nd = p, nl = P[fu][1], nr = P[fv][0];
        p = dis(P[fu][1], P[fv][1]);
        if (p > nd) nd = p, nl = P[fu][1], nr = P[fv][1];
        link(u[q[i]], v[q[i]]);
        fu = find(u[q[i]]);
        P[fu][0] = nl, P[fu][1] = nr, ans[i - 1] = max(ans[i], nd);
    }
    for (int i = 1; i <= Q; i ++) qf(ans[i]), putchar('\n');
    for (int i = 1; i <= n; i ++) 
        head[i] = u[i] = v[i] = q[i] = d[i] = w[i] = edge[i] = D[i] = 
        qed[i] = vis[i] = de[i] = P[i][0] = P[i][1] = ans[i] = qed[i] = 0;
    for (int i = 1; i <= n; i ++)
        for (int j = 0; j < 25; j ++) fa[i][j] = 0;
    tot = mx = mxp = 0;
    for (int i = 1; i <= n; i ++) e[i].clear();
}
signed main() {
    qr(T);
    while (T --) solve();
    return 0;
}