poj解题报告——2054

来源:互联网 发布:php分类信息网源码 编辑:程序博客网 时间:2024/06/10 04:45

        处理思路:利用贪心思想,每次取权值最大的节点,不断的将权值最大节点与它的父节点合并。

        过程:

       1、初始时将序列中的time[i]都置为1,w[i]置为c[i];

       2、查找最大的w[i], 返回其位置;

       3、将该位置的c[ ]与它的父节点c[ ]合并(合并过程就是C_i / T_i,C_i = c[该节点] + c[父节点],T_i = time[该节点]+time[父节点])得到新的父节点w[](w[父节点] = C_i / T_i),如果有节点与pos相连,让它指向pos的父节点;

       4、重复2、3,知道合并完;

       至于如何求出结果:初始时使ans = sum(c[i]);每次查找到一个最大权值,ans += c[i] * time[父节点];

代码如下

#include <stdio.h>#define N 1007struct node{    int t;    int p;    int c;    double w;}num[N];int n, r;int find(){    int pos,i;    double max=0;    for(i=1;i<=n;i++)        if(num[i].w>max&&i!=r)        {            max=num[i].w;            pos=i;        }    return pos;}void main(){    int i,j,a,b,pos,ans,f;    while(scanf("%d%d",&n,&r),n||r)    {        ans=0;        for(i=1;i<=n;i++)        {            scanf("%d",&num[i].c);            num[i].w =num[i].c;            num[i].t=1;            ans+=num[i].c;        }        for(i=1;i<n;i++)        {            scanf("%d%d",&a,&b);            num[b].p=a;        }        i=n;        while(i>1)        {            pos=find();            num[pos].w=0;            f=num[pos].p;            ans+=num[pos].c*num[f].t;            for(j=1;j<=n;j++)                if(num[j].p==pos)                    num[j].p=f;            num[f].c+=num[pos].c;            num[f].t+=num[pos].t;            num[f].w=(double)num[f].c/num[f].t;            i--;        }        printf("%d\n",ans);    }}  


0 0
原创粉丝点击