题号 NC13886
Shortest Path
西南交通大学第十三届ACM决赛
题意:
一棵偶数节点的树,分成n/2对,两两一组,所有组的路径之和最小是多少?
题解:
如果两个点之间相连将另外两个相连的点覆盖,那么完全可以改变相连方式

改变后路径更小,也就是说两两一组的点都不会覆盖其他点
那么每个点与其他点配对就有两者选择,一个与兄弟节点配对(中间跨过父亲点),另一个就是与父亲节点相连,这样选择肯定是最优的
如果这个节点所在的自树里有偶数个节点,那么他们内部配对就可以了(好像有什么怪怪的)
如果有奇数个节点,还有把父亲节点拉进来一起配对(这样才能组成偶数个)
来上代码:


#include<bits/stdc++.h>
using namespace std;
const int maxx=1e4+5;
typedef long long ll;
int head[maxx];
int cnt=0;
ll x,y,z;
ll ans;
struct node
{
   
	ll w,v,u,next;
}edge[maxx*2];
void addt(int u,int v,int w)
{
   
	edge[++cnt].u=u;
	edge[cnt].v=v;
	edge[cnt].w=w;
	edge[cnt].next=head[u];
	head[u]=cnt;
	
}
ll dfs(ll u,ll f,ll w)
{
   
	ll sum=1;
	for(int i=head[u];i;i=edge[i].next)
	{
   
		if(edge[i].v!=f)sum+=dfs(edge[i].v,u,edge[i].w);
	}
	if(sum%2)ans+=w;
	return sum;
}
int main()
{
   
	int T;
	int n;
	scanf("%d",&T);
	for(int i=1;i<=T;i++)
	{
   
		cin>>n;
		memset(head,0,sizeof(head));
		cnt=0;
		ans=0;
		
		for(int i=1;i<n;i++)
		{
   
			scanf("%lld%lld%lld",&x,&y,&z);
			addt(x,y,z);
			addt(y,x,z); 
		}
		dfs(1,0,0);
		printf("%d\n",ans);
		
	}
	return 0;
}
//树上dfs