您的位置:首页 > 其它

HDU_1055 && POJ_2054 Color a Tree(贪心)

2011-08-19 18:31 531 查看
  这道题整了一下午,最后还是看别人的解题报告弄出来的,先说说我的理解吧。大体处理思路是利用贪心思想,每次取权值最大的节点,不断的将权值最大节点与它的父节点合并。

过程:

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 <iostream>
#include <cstdio>

using namespace std;

const int N = 1007;

struct node
{
int t;    //time[]
int p;    //记录父节点
int c;    //c[]
double w;    //w[]
}num
;

int n, r;

int find()    //查找最大的权值,返回其位置
{
int pos;
double max = 0;
for(int i = 1; i <= n; i++)
if(num[i].w > max && i != r)    //pos不能为根节点
{
max = num[i].w;
pos = i;
}
return pos;
}

int main()
{
//freopen("data.in", "r", stdin);
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;    //初始时w[i]置为c[i];
num[i].t = 1;        //time[i] 置为1;
ans += num[i].c;    //初始ans = sum(c[i]);
}
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;        //找到后将之置0,否则影响下次查找。
f = num[pos].p;        //f为父节点
ans += num[pos].c * num[f].t;    //将找到的c[pos]*time[f]加入ans
for(j = 1; j <= n; j++)
if(num[j].p == pos)
num[j].p = f;    //如果有节点与pos相连,让它指向pos的父节点
num[f].c += num[pos].c;        //C_i = c[该节点] + c[父节点]
num[f].t += num[pos].t;        //T_i = time[该节点]+time[父节点]
num[f].w = (double)num[f].c/num[f].t;    //合并后的f节点的权值
i--;
}
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: