(较难)poj-2054 Color a tree(贪心)

链接: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()函数之后再去研究具体的函数实现。

猜你喜欢

转载自blog.csdn.net/qq_35937273/article/details/83056294