Solution
n个点n-1条双向边明显是树,而且保证必定是偶数个节点,那么就肯定是两两配对。
就一个节点来说,跟兄弟节点配对,或者跟父亲节点配对肯定是最优的。
所以只需要判断节点所在子树里面的节点数是否为偶数,如果是偶数说明不用和此节点的父亲节点配对,若为奇数则需要加上这条边,那么可设 dp[i] 为以 i 为根节点的子树的配对后的路径和,dfs下去判断子树节点即可。
Code
#include<bits/stdc++.h> #define ll long long #define fi first #define se second #define mp make_pair #define pb push_back #define inf 0x3f3f3f3f using namespace std; inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;} void put1(){ puts("Yes") ;}void put2(){ puts("No") ;}void put3(){ puts("-1"); } const int manx=1e4+5; const int mo=998244353; vector<pair<ll,ll> >g[manx]; ll cnt[manx],ans; void dfs(ll u,ll pre,ll res){ cnt[u]=1; for(auto x: g[u]){ ll v=x.fi,w=x.se; if(v==pre) continue; dfs(v,u,w); cnt[u]+=cnt[v]; } if(cnt[u]&1) ans+=res; } int main() { ll p=read(); while(p--){ ll n=read(); for(int i=1;i<=n;i++) g[i].clear(); for(int i=1;i<n;i++){ ll u=read(),v=read(),w=read(); g[u].pb(mp(v,w)); g[v].pb(mp(u,w)); } ans=0; dfs(1,0,0); printf("%lld\n",ans); } return 0; }