题面大意
- 以S为根,全部的叶子结点无法到达s,求最小消耗。
- 为什么可以得到上方结论,m=n-1,且图不连通,说明这就是一棵树。 那我们如何求得最小消耗呢?
从S为根节点依次dfs遍历整棵树,我们用dp[s]表示s结点到全部叶子结点的边权值。那么我们可以得到状态转移方程:dp[x]+=min(dp[u],w),u是子节点,w为x到u的边权。
还要注意一点,达到叶子结点应该把叶子结点的dp值改成无穷大
运行程序如下
https://ac.nowcoder.com/acm/contest/view-submission?submissionId=43371967&returnHomeType=1&uid=919749006
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;
}