地址:http://acm.scs.bupt.cn/onlinejudge/showproblem.php?problem_id=1204
EqualTree Submit: 105 Accepted:29 Time Limit: 1000MS Memory Limit: 65536KDescription
给定一棵有根树,每条边上都有一个正的长度,现在你可以延长某些边的长度,使得所有的叶子结点到根的距离相等,并且延长的长度最小。
Input
多组测试数据,以两个0结束。
第一行为两个整数N,R。N表示结点的个数(编号为0到N-1),R表示树的根。
接下来N-1行,每行三个整数a b c,表示a、b结点之间边的长度为c。
2<= N <= 1000,1<= c <= 1000
Output
对于每组测试数据,输出一行,为需要延长的最小值。
Sample Input
4 0
0 1 1
0 3 3
0 2 2
2 0
0 1 100
0 0
Sample Output
3
0
思路:从根结点开始,遍历树,用递归,根结点的每个子树分别遍历
//#include<stdio.h>
#include<iostream>
//#include<string.h>
//using namespace std;
#define MAXN 1010
int n,root;
int count[1010];
struct
{
int length;
int target;
}a[MAXN][MAXN]; //距离 以及指向目标
bool used[MAXN];
int DFS(int currentnode,int &maxdeep)
{
used[currentnode]=true; //因为两个节点是相互指向的,将当前节点制为true,可以防止下个节点返回当前节点
int cost=0;
int total=0; //已经遍历的节点个数
maxdeep=0; //最大深度
for(int i=0;i<count[currentnode];i++) //开始遍历
{
int target=a[currentnode][i].target; //当前结点指向的下一个结点
if(!used[target]) //该条件使得当前结点不会返回已经遍历过得结点
{
int deep=0; //深度
cost+=DFS(target,deep); //递归进去 把子树的距离算出来
deep+=a[currentnode][i].length; //子树距离加上根结点到当前结点距离
if(deep>maxdeep) //比较 如果当前距离大于最大距离
{
cost+=(deep-maxdeep)*total; //所有其他(total)个结点都拉长deep-maxdeep个
maxdeep=deep;
}
else
cost+=maxdeep-deep; //否则只自己拉长
total++; //遍历结点数+1
}
}
return cost;
}
int main()
{
while(scanf("%d%d",&n,&root)!=EOF)
{
memset(count, 0, sizeof count);
memset(used, 0, sizeof used);
if(n==root&&n==0)
break;
else
{
for(int i=0;i<n-1;i++)
{
int d,b,c;
scanf("%d%d%d",&d,&b,&c);
a[d][count[d]].length=c; //建立边。count[]数组记录的是有几个边。建立边时候两点互相建立
a[d][count[d]].target=b;
a[b][count[b]].length=c;
a[b][count[b]].target=d;
count[d]++;
count[b]++;
}
int maxdeep=0;
printf("%d/n",DFS(root,maxdeep));
}
}
// system("pause");
return 0;
}