题面大意

  • 以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;
}