题号 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