题目链接

代码借鉴此博:http://www.cnblogs.com/vongang/archive/2011/08/19/2146070.html

其中关于max{c[fa]/t[fa]}贪心原则,此博有很好的解释:http://www.cnblogs.com/rainydays/p/3271277.html

在此引用其中几段话:

试想,如果没有父节点排在节点之前的限制,那么这个题目非常简单,只需要将结点按照权值从大到小排列即可。加上了这个限制之后,如果权值最大的那个节点一旦满足了条件(父节点被排在了之前的某个位置),那么这个权值最大的节点一定要紧挨着这个父节点,即把这个权值最大的节点排在它所能排的最前面的位置。因为对于这个节点如果不受限制应该排在第一位,而有了限制,在满足了限制之后也应把它尽可能地排在前面。所以它一定是挨着父节点的。那么现在在最终的排列中我们确定了两个节点的前后相邻关系,将他们绑定在了一起。

试想如果保持这个相邻关系的同时去掉其他节点的限制,那么我们应该如何排列呢?我们假设绑定在一起的两节点是a和b。现有一个另外的节点x,我们看两种排列xab,abx对最终的计算结果有什么影响。x*i+a*(i+1)+b*(i+2); a*i + b*(i+1) + x*(i+2)。后者减去前者等于2x-(a+b)。即将x从ab之前挪到ab之后,ab各左移1位,结果减小a+b。x右移2位结果增加2x。因此两者谁在前谁在后我们只需要比较a+b和2x即可,也可以比较(a+b)/2和x。

将这个定理进行一下推广,绑定在一起的不一定是两个节点,可以是一个更长的序列,与这个序列进行比较看谁放在前面的也可以是一个序列。设一个序列有n1个节点,第二个序列有n2个节点。那么我们比较两者谁放在前面的时候需要比较的是(n1个权值之和×n2)和(n2个权值之和×n1)。即左移和右移产生的结果变化。当然也可以比较(n1个权值之和/n1)和(n2个权值之和/n2)。

我们可以再次进行推广,如果我们要排列的不是节点,而是许多序列的话,那么我们只需要计算每个序列权值的平均数(例如:n个节点的序列,要计算n个权值之和/n),然后按照这个平均数从大到小排列即可使得计算结果最小。这样就可以让序列与节点有了一个统一的衡量值——平均数。

这样一来,我们就可以将上面的绑定两节点的操作看成是将问题规模缩小的操作,在帮定两节点的同时我们在树中也将两节点合并,变为一个节点,即将子节点的孩子变为父节点的孩子。然后合并后的节点的权值是合并在这个节点中的所有节点的权值的平均数。我们成功的将问题规模减小了1。只需要不断这样做即可将问题缩减为只有一个节点。


以下为AC code:

//贪心:如果这棵树中有最大权值点X(非根),
//那么一旦X的父节点Y已经染色,就应该立刻染X
//于是X和Y合并成一个点集,
//新点集的权值=(新点集中所有点的权值和)/(新点集中点的个数)
//类似的,该点集可以看为一个点
//重复上述贪心思路,直到最后只剩下一个根r点集
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;const int N=1005;struct Node
{int f;//父结点int t;//时间int c;//原权值double w;//贪心权值(c/t)
}node[N];int n,r;int findPos()
{int pos;double wmax=0;for(int i=1;i<=n;i++)if(node[i].w>wmax&&i!=r){wmax=node[i].w;pos=i;}return pos;
}int main()
{while(scanf("%d%d",&n,&r)&&n+r){int pos,fa,res=0;for(int i=1;i<=n;i++){scanf("%d",&node[i].c);node[i].w=node[i].c;//将贪心权值w初始化为原权值cnode[i].t=1;//时间初始化为1res+=node[i].c;//结果初始化为sum of所有原权值c
        }int u,v;for(int i=1;i<n;i++){scanf("%d%d",&u,&v);node[v].f=u;//记录父结点
        }for(int i=1;i<n;i++){pos=findPos();//找到贪心权值最大的位置node[pos].w=0;//置0,以便下次查找时跳过之fa=node[pos].f;//fa为pos的父结点res+=node[pos].c*node[fa].t;//res+=pos原权值*fa父结点时间(node[fa].t实际上代表,点集中有几个点)for(int j=1;j<=n;j++)if(node[j].f==pos)node[j].f=fa;//若有j的父结点是pos,则将j的父结点改为fa,建立新集合node[fa].t+=node[pos].t;//更新以fa为父结点的点集内点的个数(即加上以pos为父结点的点集内点的个数)node[fa].c+=node[pos].c;//更新点集的话,那权值自然也要更新node[fa].w=(double)node[fa].c/node[fa].t;//贪心原则:新点集权值和/新点集中点的个数
        }printf("%d\n",res);}return 0;
}

转载于:https://www.cnblogs.com/atmacmer/p/5223837.html

POJ 2054 Color a Tree#贪心(难,好题)相关推荐

  1. POJ 2054 Color a Tree (贪心)

    $ POJ~2054~Color~a~Tree $ $ solution: $ 我们先从题中抽取信息,因为每个点的费用和染色的次数有关,所以我们可以很自然的想到先给权值大的节点染色.但是题目还说每个节 ...

  2. POJ 2054 Color a Tree解题报告

    题干 Bob is very interested in the data structure of a tree. A tree is a directed graph in which a spe ...

  3. POJ 2054 Color a Tree

    贪心....                    Color a Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions:  ...

  4. PKU/POJ 2054 Color a Tree

    关于树的着色. 要求从根节点出发, 遍历整棵树, 要求代价最小. 访问每个节点的代价V[i] = F[i] * C[i], C[i]为已知的值, F[i]则为访问该节点的时间. 每一步只能从已访问的节 ...

  5. POJ 2054 谜一样的贪心 TAT

    题意:给一个树形图(边为有向边的树),每个节点有一个权值Ci,要求给每个节点染色,要求是如果想对一个节点染色,那么必须保证它的父节点已经被染过色.求一个最小的染色代价,每个节点的代价是ki*Ci,ki ...

  6. UPC1430 Color a Tree(贪心)

    链接:http://exam.upc.edu.cn/problem.php?cid=1430&pid=19 题意: 一棵树,n个节点,n-1条边,每个节点有权值val.Time为当前时间,初始 ...

  7. HDU 6241 Color a Tree

    Color a Tree 题目大意:一棵树,根为1.某些点有一些限制.限制A: 该$x_i$点子树染色点至少$y_i$个. 限制B: 该$x_i$点子树外染色至少$y_i$个.求最少染色点数. 首先是 ...

  8. poj 3013 Big Christmas Tree(最短路变形)

    传送门:POJ 3013 Big Christmas Tree 描述: Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K To ...

  9. 史上最难逻辑题!据说99.9%的人都做不出来……

    全世界只有3.14 % 的人关注了 爆炸吧知识 非常「逻辑」 撩人于无形 普林斯顿大学博士生 Raymond Smullyan 是一位非常厉害逻辑高手. 在Smullyan与他非常迷恋的女音乐家的第一 ...

  10. HDU_1055 POJ_2054 Color a Tree(贪心)

    这道题整了一下午,最后还是看别人的解题报告弄出来的,先说说我的理解吧.大体处理思路是利用贪心思想,每次取权值最大的节点,不断的将权值最大节点与它的父节点合并. 过程: 1.初始时将序列中的time[i ...

最新文章

  1. docker-compose的安装与简单使用
  2. python绘图教程_pyplot绘图教程
  3. EOJ_1049_三元组稀疏矩阵相加
  4. 为.netcore助力--WebApiClient正式发布core版本
  5. javascript实现代码高亮
  6. 详解Vue八大生命周期钩子函数
  7. java nio 强制关闭_Java NIO服务器:远程主机强迫关闭了一个现有的连接
  8. 基于STM32实现的普通灯泡调光控制器
  9. UI设计师必备的网站推荐
  10. fshc模块fsch2mcu_if理解
  11. oracle连表图解,oracle 表连接方式解析
  12. xshell如何设置选中复制_Xshell
  13. SATI--文献题录开源程序
  14. C++ MFC调用易语言模块
  15. simulink 调整系统采样时间 示波器显示时间
  16. NLP实践——Few-shot事件抽取《Building an Event Extractor with Only a Few Examples》
  17. 淘宝开放平台接口接口,订单R2权限接口淘宝开放平台R2权限,淘宝开放平台进存销应用,top平台接口,淘宝应用市场接口,ERP软件订单接口,淘上淘接口,
  18. linux安装windows字体
  19. SQL SERVER 远程主机强迫关闭一个现有连接
  20. 利用LabVIEW开发应变量测试

热门文章

  1. 可变参数列表来实现printf函数的输出
  2. 正文内容 SQL Server 数据库清除日志
  3. cisco keepalive
  4. 突然发现到今天已经很难找到对底层理解这么透彻的人
  5. 学习《Core IO学习心得》
  6. iPhone 6 Plus实际分辨率为2208x1242的问题
  7. navigationcontroller和navigationbar和navigationitem之间的区别以及不用nib实现点击屏幕关闭虚拟键盘20130911...
  8. poj 2778 DNA Sequence
  9. 【vs2019MFC】msvcrtd.lib(exe_main.obj) : error LNK2019: 无法解析的外部符号 _main,该符号在函数 “int __cdecl invoke_mai
  10. Enyim.Caching 客户端配置及示例