是看着别人的博客来写的。。学习他的方法吧。第二题了哦,加油加油。 要看看去贪心算法咯
#include <stdio.h>
#include <stdlib.h>
#define MAXN 1010
int n,r;
int c[MAXN];
int parent[MAXN];
bool visited[MAXN];
int next[MAXN];
int prev[MAXN];
int rank[MAXN];
int sum[MAXN];
int find()
{
double max=0;
int i,flg=-1;
for(i=1;i<=n;i++)
if(max<sum[i]*1.0/rank[i] && !visited[i])
{
max=sum[i]*1.0/rank[i];
flg=i;
}
return flg;
}
void uni(int x)
{//合并节点,并把他们按顺序排好
int i;
for(i=parent[x];prev[i]!=-1;i=prev[i]); //合并节点
rank[i]+=rank[x];
sum[i]+=sum[x];
for(i=parent[x];next[i]!=-1;i=next[i]); //排序,接到最后一个节点上
next[i]=x;
prev[x]=i;
visited[x]=true;
}
int main()
{
while(scanf("%d %d",&n,&r),n && r)
{
int i;
for(i=1;i<=n;i++)
{
scanf("%d",&c[i]);
visited[i]=false;
prev[i]=next[i]=-1;
rank[i]=1; //合并后,集合中的规模
sum[i]=c[i]; //集合的和
}
for(i=1;i<n;i++)
{ //输入n-1个节点的父子关系
int a,b;
scanf("%d %d",&a,&b);
parent[b]=a;
}
visited[r]=true;
while(true)
{
int u=find();
if(u==-1)
break;
uni(u);
}
int cnt=0,ans=0; //cnt用于记录时间
for(i=r;i!=-1;i=next[i])
ans+=(++cnt)*c[i];
printf("%d\n",ans);
}
return 0;
}