一、题目:Color a tree
二、题意:http://acm.pku.edu.cn/JudgeOnline/problem?id=2054
三、方法:自底向上的DP
四、代码:
#include "stdio.h"
#include "string.h"
int c[1010][3], praent[1010];
int main()
{
freopen("1.txt", "r", stdin);
int i;
int n, r;
while (scanf("%d%d",&n, &r))
{
if (n == 0 && r == 0)
{
break;
}
for (i = 1; i <= n; i++)
{
scanf("%d",&c[i][0]);
c[i][1] = c[i][0];
c[i][2] = 1; //记录该节点需要花费的时间,全部设为1
}
praent[r] = -1; //最高的节点的父亲
int a, b;
for (i = 0; i < n - 1; i++)
{
scanf("%d%d", &a, &b);
praent[b] = a; //连接所有的节点
}
int pos, l;
//自底向上的DP
//思想:将较大的Ci值与较小的时间相乘
while (1)
{
pos = 0;
//寻找符合条件的Ci
for (i = 1; i <= n; i++)
{
if (i != r && c[i][2] != 0)
{
if (pos == 0 || c[pos][1] * c[i][2] < c[pos][2] * c[i][1])
{
pos = l = i;
}
}
}
if (pos == 0)
{
break;
}
//例如:
//右节点:
//应该为:1*1+1*2+4*3=5
//分为:(4*1+4+1)+5*1+1
c[praent[l]][0] += c[praent[l]][2] * c[l][1] + c[l][0];
c[praent[l]][1] += c[l][1];
c[praent[l]][2] += c[l][2];
c[l][0] = c[l][1] = c[l][2] = 0; //已经着色
}
printf("%d/n",c[r][0]);
}
return 0;
}