题意:把图中所有节点分成对点,然后把分成的每对点的距离求和,并且要求和最小
题解: 典型的树形结构
所以我们考虑的时候,如果当前节点的子节点数为偶数那是否表示,不需要额外添加边
如图(图有点丑.....)对于下面的那个节点他有偶数个节点,两两配对即可
而对于子节 点有奇数个,那么两两配对,对于小小根还剩余1个子节点,而这个节点配对最好的方法就是和小小根配对,而对于小根的子节点数位偶数,跳过,对于根节点的节点数是奇数,那么它要和自己的某一个子节点结合
所以就是搜索全图,如果当前节点的子树节点(子树包括当前节点)为偶数不需要处理,奇数加上当前节点与其根节点的边权
时间复杂度
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1e18
ll const maxn=2e6+10;
struct node ///链式前向星存图
{
ll to,next,val;///终点,同起点的上一条边的编号,边权
} edge[maxn]; ///边集
ll n,t,u,v,w,cnt,head[maxn],ans;
void add(ll u,ll v,ll w)
{
edge[++cnt].next = head[u];///以u为起点上一条边的编号,也就是与这个边起点相同的上一条边的编号
edge[cnt].to=v;///终点
edge[cnt].val=w;///权值
head[u]=cnt;///更新以u为起点上一条边的编号
}
void solve();
int main()
{
int t;
scanf("%d",&t);
while(t--)
solve();
}
ll dfs(ll a,ll b,ll c)
{
ll tc=1;
for(int i=head[a]; i!=0; i=edge[i].next)
{
ll w=edge[i].to;
ll v=edge[i].val;
if(w==b)
continue;
tc+=dfs(w,a,v);
}
if(tc%2==1)
ans+=c;
return tc;
}
void solve()
{
memset(head,0,sizeof(head));
scanf("%lld",&n);
cnt=0,ans=0;
for(int i=1; i<n; i++)
{
scanf("%lld%lld%lld",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
dfs(1,0,0);
printf("%lld\n",ans);
}

京公网安备 11010502036488号