把n个城市分成n/2对,这样n/2对城市之间的长度之和最小。 保证n是均分

样例一:
我们最小的分法是1-2,2-3,答案是5+6=11 其他分法均比这个要大

样例二:
图片说明

我们选择的是1-3,2-4,5-6 合计5+(3+9)+(10+4)=31

我可以发现,选择2个城市,尽可能要不重复,如果出现交叉重复的,那么不能保证最小了,当某个节点x的子树大小为奇数的时候,我们需要加上节点x和父节点的贡献。在dfs到叶子节点的时候,返回上来,判断下该节点子树大小是不是奇数,是奇数加上其贡献即可。

代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N=1e4+100;

ll head[N<<1],cnt;
ll t,n;
ll u,v,val;
ll ans;

struct Edge
{
    ll e;
    ll to;
    ll data;
}edge[N<<1];

void add_edge(ll u,ll v,ll val)
{
    cnt++;
    edge[cnt].e=v;
    edge[cnt].to=head[u];
    edge[cnt].data=val;
    head[u]=cnt;
}

ll dfs(ll u,ll f,ll val)
{
    ll ct=1;//当前子树大小 
    for(ll i=head[u];i!=0;i=edge[i].to)
    {
        ll v=edge[i].e;
        ll w=edge[i].data;
        if(v==f)continue;//如果当前节点连接的下一个节点是他的父节点,continue掉 
        ct+=dfs(v,u,w);
    }
    if(ct%2==1)//子树大小是奇数,加上他与父节点的贡献 
    {
        ans+=val; 
    }
    return ct;
}

int main()
{
    scanf("%lld",&t);
    while(t--)
    {
        memset(head,0,sizeof(head));
        ans=0;
        cnt=0;
        scanf("%lld",&n);
        for(ll i=0;i<n-1;i++)
        {
            scanf("%lld%lld%lld",&u,&v,&val);
            add_edge(u,v,val);
            add_edge(v,u,val);
        }
        dfs(1,0,0);
        printf("%lld\n",ans);
    }
    return 0;
}