http://acm.hdu.edu.cn/showproblem.php?pid=4118
Problem Description
Nowadays, people have many ways to save money on accommodation when they are on vacation.
One of these ways is exchanging houses with other people.
Here is a group of N people who want to travel around the world. They live in different cities, so they can travel to some other people‘s city and use someone‘s house temporary. Now they want to make a plan that choose a destination for each person. There are
2 rules should be satisfied:
1. All the people should go to one of the other people‘s city.
2. Two of them never go to the same city, because they are not willing to share a house.
They want to maximize the sum of all people‘s travel distance. The travel distance of a person is the distance between the city he lives in and the city he travels to. These N cities have N - 1 highways connecting them. The travelers always choose the shortest
path when traveling.
Given the highways‘ information, it is your job to find the best plan, that maximum the total travel distance of all people.
Input
The first line of input contains one integer T(1 <= T <= 10), indicating the number of test cases.
Each test case contains several lines.
The first line contains an integer N(2 <= N <= 105), representing the number of cities.
Then the followingN-1 lines each contains three integersX, Y,Z(1 <= X, Y <= N, 1 <= Z <= 106), means that there is a highway between city X and city Y , and length of that highway.
You can assume all the cities are connected and the highways are bi-directional.
Output
For each test case in the input, print one line: "Case #X: Y", where X is the test case number (starting with 1) and Y represents the largest total travel distance of all people.
Sample Input
2 4 1 2 3 2 3 2 4 3 2 6 1 2 3 2 3 4 2 4 1 4 5 8 5 6 5
Sample Output
Case #1: 18 Case #2: 62
/** hdu 4118 树形dp 题目大意:一棵n节点的树,每个节点有一个人,每个人离开自己的位置到另一个位置,每个位置只能有一个人,问这n个人移动距离和的最大值。 解题思路:(转)如果找出树的重心就可以把树分成左右两部分,左边的点跟右边的点交换位置,两点交换位置的距离=两点到根节点的距离之和的2倍, 总距离就是所有点到根节点距离之和的2倍了,当时犹豫了一下,如果节点数是奇数的话,这样是不是根节点没换位置呢?后来一想, 这种交换位置每个点走的路径都经过根节点,根节点跟任意一个点交换一下就可以了,答案还是一样的。 树形DP:我们可以统计没条边被走了多少次,一条边可以把点分为左右两部分,两部分中点数较少的一部分都要离开自己的位置去另一边, 这条边被走了min(son[u](右边点数),son[v])*2次,点数多的一部分有的位置是没变的,但是我们这样把每条边都操作一遍后,所有点的位置都变了。 注:递归dfs会爆内存。 */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; typedef long long LL; const int maxn=100005; struct note { int v,w,next; } edge[maxn*2]; int head[maxn],ip; int n,vis[maxn],num[maxn],sta[maxn]; LL ans; void init() { memset(head,-1,sizeof(head)); ip=0; } void addedge(int u,int v,int w) { edge[ip].v=v,edge[ip].w=w,edge[ip].next=head[u],head[u]=ip++; } ///递归形式会超出内存 void dfs(int u,int pre) { for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==pre)continue; dfs(v,u); num[u]+=num[v]; ans+=(LL)edge[i].w*2*min(num[v],n-num[v]); } num[u]++; } ///用栈实现非递归形式 void dfs1(int u) { memset(vis,0,sizeof(vis)); int top=0; sta[top++]=u; vis[u]=1; while(top>0) { bool flag=1; int t=sta[top-1]; for(int i=head[t]; i!=-1; i=edge[i].next) { int v=edge[i].v; if(vis[v])continue; sta[top++]=v; vis[v]=1; flag=0; } if(flag==0)continue; for(int i=head[t]; i!=-1; i=edge[i].next) { int v=edge[i].v; if(num[v]!=0) { num[t]+=num[v]; ans+=(LL)edge[i].w*2*min(num[v],n-num[v]); } } num[t]++; top--; } } int main() { int T,tt=0; scanf("%d",&T); while(T--) { scanf("%d",&n); init(); for(int i=1; i<n; i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } ans=0; memset(num,0,sizeof(num)); ///dfs1(1); dfs(1,-1); printf("Case #%d: %I64d\n",++tt,ans); } return 0; }