树形dp

直接表示 为根的子树处理完的代价
转移的时候枚举是断掉当前的边还是断子树的边即可。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>

#define Re register
#define LL long long
#define U unsigned
#define FOR(i,a,b) for(Re int i = a;i <= b;++i)
#define ROF(i,a,b) for(Re int i = a;i >= b;--i)
#define SFOR(i,a,b,c) for(Re int i = a;i <= b;i+=c)
#define SROF(i,a,b,c) for(Re int i = a;i >= b;i-=c)
#define CLR(i,a) memset(i,a,sizeof(i))
#define BR printf("--------------------\n")
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

const int MAXN = 100000+5;

struct Edge{
    int to,w,next;
}e[MAXN<<1];
int head[MAXN],cnt;
LL f[MAXN];

inline void add(int u,int v,int w){
    e[++cnt] = (Edge){v,w,head[u]};head[u] = cnt;
}

void dfs(int v,int fa=0){
    bool flag = true;
    for(int i = head[v];i;i = e[i].next){
        if(e[i].to == fa) continue;
        flag = false;
        dfs(e[i].to,v);
        f[v] += std::min(1ll*e[i].w,f[e[i].to]);
    }
    if(flag) f[v] = INT_MAX;
}

int N,root;

int main(){
    scanf("%d%d",&N,&root);
    FOR(i,1,N-1){
        int u,v,w;scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);add(v,u,w);
    }
    dfs(root);
    printf("%lld\n",f[root]);
    return 0;
}