From e4ae3297833cf3e85aa6fc9dead4d73d6db095c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B5=B7?= <10402852@qq.com> Date: Wed, 17 Jan 2024 08:19:30 +0800 Subject: [PATCH] 'commit' --- TangDou/Topic/HuanGenDp/P6419.cpp | 74 ++++++++++++++++++------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/TangDou/Topic/HuanGenDp/P6419.cpp b/TangDou/Topic/HuanGenDp/P6419.cpp index 3602e1b..0f1a1d2 100644 --- a/TangDou/Topic/HuanGenDp/P6419.cpp +++ b/TangDou/Topic/HuanGenDp/P6419.cpp @@ -2,33 +2,39 @@ using namespace std; const int N = 500010, M = N << 1; #define int long long + +// 链式前向星 +int e[M], h[N], idx, w[M], ne[M]; +void add(int a, int b, int c = 0) { + e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; +} + int n, m, k; -#define INF 1e18 + int sz[N]; // 以u为根节点是否有人 int g[N]; // 从u出发把u子树上的人都送回家再回到u所需要的时间 -vector> vec[N]; -int max1[N]; // u的子树中最长链的长度 -int max2[N]; // u的子树中次长链 -int up[N]; // 不在u的子树内,距离u最远的那个人的家到u的距离 -int id[N]; // 最长链条是哪条链 -int ans[N]; // 从u出发把所有点都送回家再回到u的结果 -// ans[i] -max(up[i],max1[i]); +int mx1[N]; // u的子树中最长链的长度 +int mx2[N]; // u的子树中次长链 +int up[N]; // 不在u的子树内,距离u最远的那个人的家到u的距离 +int id[N]; // 最长链条是哪条链 +int ans[N]; // 从u出发把所有点都送回家再回到u的结果 + +// ans[i] -max(up[i],mx1[i]); void dfs1(int u, int fa) { - for (auto ts : vec[u]) { - int v = ts.first; - int w = ts.second; + for (int i = h[u]; ~i; i = ne[i]) { + int v = e[i]; if (v == fa) continue; dfs1(v, u); if (sz[v]) { - g[u] += g[v] + 2 * w; - int now = max1[v] + w; - if (now >= max1[u]) { - max2[u] = max1[u]; - max1[u] = now; + g[u] += g[v] + 2 * w[i]; + int now = mx1[v] + w[i]; + if (now >= mx1[u]) { + mx2[u] = mx1[u]; + mx1[u] = now; id[u] = v; - } else if (now >= max2[u]) { - max2[u] = now; + } else if (now >= mx2[u]) { + mx2[u] = now; } } sz[u] += sz[v]; @@ -36,22 +42,21 @@ void dfs1(int u, int fa) { } void dfs2(int u, int fa) { - for (auto ts : vec[u]) { - int v = ts.first; - int w = ts.second; + for (int i = h[u]; ~i; i = ne[i]) { + int v = e[i]; if (v == fa) continue; if (sz[v] == k) { ans[v] = g[v]; up[v] = 0; } else if (sz[v] == 0) { - ans[v] = ans[u] + 2 * w; - up[v] = max(up[u], max1[u]) + w; + ans[v] = ans[u] + 2 * w[i]; + up[v] = max(up[u], mx1[u]) + w[i]; } else if (sz[v] && sz[v] != k) { ans[v] = ans[u]; if (id[u] == v) { - up[v] = max(max2[u], up[u]) + w; + up[v] = max(mx2[u], up[u]) + w[i]; } else - up[v] = max(up[u], max1[u]) + w; + up[v] = max(up[u], mx1[u]) + w[i]; } dfs2(v, u); @@ -59,21 +64,26 @@ void dfs2(int u, int fa) { } signed main() { - cin >> n >> k; - for (int i = 1; i < n; i++) { + // 初始化链式前向星 + memset(h, -1, sizeof h); + + cin >> n >> k; // n个节点,要接k个人 + for (int i = 1; i < n; i++) { // n-1条边 int a, b, c; cin >> a >> b >> c; - vec[a].push_back({b, c}); - vec[b].push_back({a, c}); + add(a, b, c), add(b, a, c); } + for (int i = 1; i <= k; i++) { int x; cin >> x; - sz[x] = 1; + sz[x] = 1; // x节点有一个人 } + // 第一次dfs dfs1(1, 0); ans[1] = g[1]; + // 第二次dfs dfs2(1, 0); - int minn = INF; - for (int u = 1; u <= n; u++) cout << ans[u] - max(up[u], max1[u]) << endl; + + for (int u = 1; u <= n; u++) cout << ans[u] - max(up[u], mx1[u]) << endl; } \ No newline at end of file