链接:http://poj.org/problem?id=2054
这个问题的题解在网络上有很多:
推荐:https://www.cnblogs.com/rainydays/archive/2013/08/20/3271277.html
代码可以参考我的:
#include <cstdlib>
#include <cstdio>
using namespace std;
const int maxn=1005;
struct node //邻接表表示
{
int index;
node *next;
}Node[maxn];
int value[maxn];
int num[maxn];
int far[maxn];
int flag[maxn];
int n,r;
int Sum;
void add(int x,int y) ///向邻接表中加入点
{
node *no=(node *)malloc(sizeof (node));
no->index=y;
no->next=Node[x].next;
Node[x].next=no;
}
void merger(int par,int son) ///合并子节点和父节点 然后把子节点的孩子节点的父节点进行更改
{
value[par]+=value[son];
num[par]+=num[son];
node *no=Node[son].next;
while(no!=NULL)
{
far[no->index]=par;
no=no->next; //因为这棵树是用邻接表存储的,所以这里代表的是同一父节点下的下一个子节点
}
}
int find1()
{
double t=-1.0;
int index;
for(int i=1;i<=n;i++)
if(!flag[i]&&double(value[i])/num[i]>t&&i!=r)
{
index=i;
t=double(value[i])/num[i];
}
return index;
}
void cal()
{
for(int i=1;i<n;i++) 是除了根节点的节点
{
int index=find1();
flag[index]=true;
int par=far[index];
while(flag[par]) par=far[par];
Sum+=value[index]*num[par];
merger(par,index);
}
Sum+=value[r]; //最后一定要加上根节点
}
int main()
{
while(scanf("%d%d",&n,&r),n|r)
{
memset(flag,0,sizeof flag);
for(int i=1;i<=n;i++)
{
num[i]=1;
scanf("%d",&value[i]);
Node[i].next=NULL;
}
int aa,bb;
for(int i=1;i<n;i++) ///注意这里,是输入边,所以是<n
{
scanf("%d%d",&aa,&bb);
add(aa,bb);
far[bb]=aa;
}
Sum=0;
cal();
printf("%d\n",Sum);
}
return 0;
}
看代码一定要从main()函数看起,然后把main()中用到的函数的实现什么功能知道,顺一遍main()函数之后再去研究具体的函数实现。