题意

给定一棵树和根节点,每条边有边权。删去一些边,使得根节点和叶子节点不连通,求删的边的边权和最小值。

分析

树形dp。
表示 不与子树中的叶子节点相连的最小值。
考虑 的每一个儿子 和边权
显然断 中叶子节点的最优值为
然后 即可。

代码如下

#include <bits/stdc++.h>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#define N 100005
using namespace __gnu_pbds;
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }
    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};
LL z = 1;
LL read(){
    LL x, f = 1;
    char ch;
    while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
    x = ch - '0';
    while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
    return x * f;
}
int ksm(int a, int b, int p){
    int s = 1;
    while(b){
        if(b & 1) s = z * s * a % p;
        a = z * a * a % p;
        b >>= 1;
    }
    return s;
}
struct node{
    int a, b, n;
    LL c;
}d[N * 2];
int cnt, h[N], a[N], fa[N];
LL f[N];
void cr(int a, int b, LL c){
    d[++cnt].a = a; d[cnt].b = b; d[cnt].c = c; d[cnt].n = h[a]; h[a] = cnt;
}
void dfs(int a){
    int i, b;
    LL c, s = 0, zhi = 0;
    f[a] = (z << 40);
    for(i = h[a]; i; i = d[i].n){
        b = d[i].b;
        c = d[i].c;
        if(b == fa[a]) continue;
        zhi = 1;
        fa[b] = a;
        dfs(b);
        s += min(c, f[b]);
    }
    if(zhi == 1) f[a] = s;
}
int main(){
    int i, j, n, m, s, a, b, c;
    n = read(); m = read(); s = read();
    for(i = 1; i <= m; i++){
        a = read(); b = read(); c = read();
        cr(a, b, c);
        cr(b, a, c);
    }
    dfs(s);
    printf("%lld", f[s]);
    return 0;
}