题意:n个点的一棵树,选出n/2个点对,使得点对之间两点距离之和最小,n保证偶数
sum[i]是以结点i包括结点i的子树结点个数,当sum[i]为偶数时,只需要让这颗子树中的点两两相连,代价就是该子树的所有边;当sum[i]为奇数时,就需要另外一个点与外面(即除这颗子树外)的点相连,最优当然是选择这颗子树的根,这时这颗子树的根与它的父节点相连的这条边就会对答案贡献
#include <cstdio> #include <cstring> using namespace std; typedef long long ll; const int N = 1e4+10; struct Edge{ int to,nex; ll w; }e[N*2]; ll ans; int n,head[N],idx; int sum[N]; void addedge(int u,int v,ll w){ e[idx].to = v; e[idx].nex = head[u]; e[idx].w = w; head[u] = idx++; } int dfs(int u,int fa,ll w){ sum[u] = 1; for(int i = head[u];~i;i = e[i].nex){ int v = e[i].to; if(v == fa) continue; sum[u]+=dfs(v,u,e[i].w); } if(sum[u]&1) ans+=w; return sum[u]; } int main(){ int t;scanf("%d",&t); while(t--){ scanf("%d",&n); memset(head,-1,sizeof(head)); idx = 0; for(int i = 1;i < n;i++){ int u,v;ll w; scanf("%d%d%lld",&u,&v,&w); addedge(u,v,w);addedge(v,u,w); } ans = 0; dfs(1,-1,0); printf("%lld\n",ans); } return 0; }