题目

Rinne 最近了解了如何快速维护可支持插入边删除边的图,并且高效的回答一下奇妙的询问。
她现在拿到了一个 n 个节点 m 条边的无向连通图,每条边有一个边权 w_i 现在她想玩一个游戏:选取一个 “重要点” S,然后选择性删除一些边,使得原图中所有除 S 之外度为 1 的点都不能到达 S。
定义删除一条边的代价为这条边的边权,现在 Rinne 想知道完成这个游戏的最小的代价,这样她就能轻松到达 rk1 了!作为回报,她会让你的排名上升一定的数量。
2≤S≤N≤10^5,M=N−1,保证答案在 C++ long long 范围内。


做法






代码

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define debug(a) cout << #a ": " << a << endl
using namespace std;
typedef long long ll;
const int N = 1e6 + 7;
const int inf = 0x3f3f3f3f;
int n, m, s, val[N], mrk[N];
vector<pair<int,int> > g[N];
ll dp[N];
void dfs(int u, int p){
    if (g[u].size() == 1 && u != s) dp[u] = inf;
    for (int i = 0; i < g[u].size(); ++i){
        int v = g[u][i].first;
        ll w = g[u][i].second;
        if (v == p) continue;
        dfs(v, u);
        dp[u] += min(dp[v], w);
    }
}
int main(void){
    IOS;
    cin >> n >> m >> s;
    for (int i = 0; i < m; ++i){
        int u, v, w; cin >> u >> v >> w;
        g[u].push_back(make_pair(v, w));
        g[v].push_back(make_pair(u, w));
    }
    dfs(s, s);
    cout << dp[s] << endl;
    return 0;
}