P7232 [JSOI2014] 支线剧情 2 - 题解
简单手玩一下,可以发现一定存在一种最优方案,能够一棵子树一棵子树地访问掉所有叶结点。
考虑树形
设
另一种是不下放存档点,那么就需要从点
当然,还可以任选一棵子树作为最后一个被处理的子树,使得处理完它后不需要再回到结点
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
constexpr int N = 1e6 + 10;
struct Graph {
int head[N], total, v[N << 1], w[N << 1], suf[N << 1];
Graph() {memset(head, -1, sizeof head);}
inline void addedge(int x, int y, int t) {
suf[total] = head[x]; head[x] = total;
v[total] = y, w[total] = t; total++;
}
} G;
i64 f[N], g[N], s[N], dep[N];
void dfs(int u, int fa) {
int child = 0;
for(int i = G.head[u]; ~i; i = G.suf[i]) {
int v = G.v[i], w = G.w[i];
if(v == fa) continue;
dep[v] = dep[u] + w; dfs(v, u);
child++; s[u] += s[v]; g[u] += g[v] + w * s[v];
}
if(child == 0) s[u] = 1;
i64 del = 0;
for(int i = G.head[u]; ~i; i = G.suf[i]) {
int v = G.v[i], w = G.w[i];
if(v == fa) continue;
i64 cur = min(f[v] + w + dep[u], g[v] + w * s[v]);
i64 it = f[v] + w;
del = max(del, cur - it);
f[u] += cur;
}
f[u] -= del;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
int n; cin >> n;
for(int i = 1; i <= n; i++) {
int k; cin >> k;
while(k--) {
int v, w; cin >> v >> w;
G.addedge(i, v, w), G.addedge(v, i, w);
}
}
dfs(1, -1);
cout << f[1] << "\n";
}