树形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; }