树形DP
Rinne Loves Edges
https://ac.nowcoder.com/acm/problem/22598
题面大意
- 以S为根,全部的叶子结点无法到达s,求最小消耗。
- 为什么可以得到上方结论,m=n-1,且图不连通,说明这就是一棵树。 那我们如何求得最小消耗呢?
从S为根节点依次dfs遍历整棵树,我们用dp[s]表示s结点到全部叶子结点的边权值。那么我们可以得到状态转移方程:dp[x]+=min(dp[u],w),u是子节点,w为x到u的边权。
还要注意一点,达到叶子结点应该把叶子结点的dp值改成无穷大
Code
#include <bits/stdc++.h> using namespace std; #define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0) typedef long long ll; inline int read() { int s = 0, w = 1; char ch = getchar(); while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); } while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar(); return s * w; } const int N = 1e5 + 7; struct Node { int v; ll w; }; vector<Node> e[N]; ll dp[N]; void dfs(int x, int fa) { bool flag = true; for (auto it : e[x]) { if (it.v != fa) { flag = false; dfs(it.v, x); dp[x] += min(it.w, dp[it.v]); } } if (flag) dp[x] = 1e18; } int main() { int n = read(), m = read(), s = read(); for (int i = 1; i <= m; ++i) { int u = read(), v = read(), w = read(); e[u].push_back({ v,w }); e[v].push_back({ u,w }); } dfs(s, 0); printf("%lld\n", dp[s]); return 0; }
每日一题 文章被收录于专栏
每日一题