题解:P12849 [蓝桥杯 2025 国 A] 公路【数据强度待检验】
WorldMachine · · 题解
抽象扭曲魔怔做法。
对每种颜色分别计算答案,考虑断开所有该种颜色的边,那么共有
于是现在问题变成了颜色
擦着过的。
#include <bits/stdc++.h>
using namespace std;
#define il inline
#define IOSIZE (1 << 20)
char buf[IOSIZE], *p1 = buf, *p2 = buf;
#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, IOSIZE, stdin), p1 == p2) ? EOF : *p1++)
il int read() { int x = 0; char c = 0; while (c < '0' || c > '9') c = gc(); while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc(); return x; }
typedef long long ll;
const int N = 5e5 + 5;
int n, u[N], v[N], fa[N], siz[N], top, stk[N]; ll C[N], ans, cur;
basic_string<int> t[N << 2];
il int get(int x) { return x == fa[x] ? x : get(fa[x]); }
il void merge(int x, int y) {
if ((x = get(x)) == (y = get(y))) return;
if (siz[x] > siz[y]) swap(x, y);
cur -= C[siz[x]], cur -= C[siz[y]];
fa[x] = y, siz[y] += siz[x], cur += C[siz[y]];
stk[++top] = x;
}
il void upd(int p, int l, int r, int L, int R, int x) {
if (L <= l && r <= R) return t[p] += x, void();
int mid = l + r >> 1;
if (L <= mid) upd(p << 1, l, mid, L, R, x);
if (R > mid) upd(p << 1 | 1, mid + 1, r, L, R, x);
}
il void roll(int t) {
while (top > t) {
int x = stk[top--], y = fa[x];
cur -= C[siz[y]], fa[x] = x, siz[y] -= siz[x];
cur += C[siz[x]], cur += C[siz[y]];
}
}
il void solve(int p, int l, int r) {
int tot = top;
for (int i = 0, s = t[p].size(); i < s; i++) merge(u[t[p][i]], v[t[p][i]]);
if (l == r) ans -= cur;
else {
int mid = l + r >> 1;
solve(p << 1, l, mid), solve(p << 1 | 1, mid + 1, r);
}
roll(tot);
}
int main() {
n = read();
for (int i = 1, w; i < n; i++) {
u[i] = read(), v[i] = read(), w = read();
if (w > 1) upd(1, 1, n, 1, w - 1, i);
if (w < n) upd(1, 1, n, w + 1, n, i);
}
for (int i = 1; i <= n; i++) fa[i] = i, siz[i] = 1, C[i] = (ll)i * (i - 1);
ans = C[n] * n, solve(1, 1, n), cout << ans;
}