$ POJ2054ColoraTree $



$ solution: $

我们先从题中抽取信息,因为每个点的费用和染色的次数有关,所以我们可以很自然的想到先给权值大的节点染色。但是题目还说每个节点染色前它的父亲节点也必须被染色,这就有了很多的后效性。

暂时没有办法贪心,我们就只能再找找性质。博主首先想到的是从叶子节点考虑,叶子节点里权值最小的一定最后染色。但是经过自我hack,这个结论也是错的。举个栗子:5-1-1-1-8,这条链上如果以左边第一个1为根,先染5会更优。

叶子节点我们拿他没办法,所以我们看看树枝,然后我们可以猜一个贪心:对于某一个节点,在它的所有儿子节点中最早被染色的一定是最大的那个。好吧,这个贪心也是错的,每个节点的费用会受到子节点的影响。

那,什么情况下不会有后效性呢?我们可以从全局考虑,找整颗树上权值最大的节点,这个节点一定在它父亲染色后第一个被染色。这个顺序绝不会变(是一个正确的贪心)。但是我们找到这个最大的节点之后又该如何?找第二大的节点?可这个结论还适用吗?

这里我们有一个常用套路,在之前贪心是我们其实就可以想到:对每个点设定一个新的权值。但是这个设新权值的办法在最开始不好用,它要猜。不过我们在想出上面这个贪心后就可以很容易设出来这个权值。因为上面说过了最大的节点一定在它父亲染色后第一个被染色。这,我们不就相当与将两个点合并吗?但是新权值怎么设?我们仔细思考一下就可以知道新权值为新节点所包含节点的权值和除以包含的节点数

然后我们直接按照这个方法贪心,找最大用优先队列,每次合并时计算一下局部答案即可。复杂度 $ O(nlogn) $



$ code: $

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set> #define ll long long
#define db double
#define rg register int using namespace std; db d[1005];
int n,root,top;
int s[1005];
int fa[1005];
int tot[1005];
int sum[1005];
int ans[1005];
bool use[1005]; struct pi{
db v; int id;
inline bool operator <(const pi &x)const{
return v<x.v;
}
}a[1005]; priority_queue<pi> q; inline int qr(){
register char ch; register bool sign=0; rg res=0;
while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
if(sign)return -res; else return res;
} inline int get(int x){
if(x==s[x])return x;
return s[x]=get(s[x]);
} int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
while(~scanf("%d%d",&n,&root)){
if(!n&&!root)break;
for(rg i=1;i<=n;++i){
rg x=qr(); d[i]=a[i].v=x; a[i].id=i; q.push(a[i]); //读入
s[i]=i; tot[i]=1; use[i]=0; sum[i]=ans[i]=x;//预处理
} use[root]=1; //根节点没有父亲,不能合并,所以直接判它已被使用
for(rg i=1;i<n;++i){
rg x=qr(),y=qr(); fa[y]=x; //读入父子关系y
}
for(rg i=1;i<n;++i){ //有且仅有n-1次合并
while(use[q.top().id]||d[q.top().id]!=q.top().v)q.pop();//有一些节点被用过,是无效的
rg x=q.top().id,y=get(fa[x]); q.pop(); //x为儿子,y为父亲
s[x]=y; use[x]=1; ans[y]+=ans[x]+sum[x]*tot[y]; //更新节点信息
tot[y]+=tot[x]; sum[y]+=sum[x]; //更新节点信息
pi z; d[y]=z.v=(db)sum[y]/tot[y]; z.id=y; q.push(z); //合并节点
}printf("%d\n",ans[root]); //根节点的答案才是最终答案
}
return 0;
}

POJ 2054 Color a Tree (贪心)的更多相关文章

  1. POJ 2054 Color a Tree#贪心(难,好题)

    题目链接 代码借鉴此博:http://www.cnblogs.com/vongang/archive/2011/08/19/2146070.html 其中关于max{c[fa]/t[fa]}贪心原则, ...

  2. POJ 2054 Color a Tree

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

  3. 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 ...

  4. poj 2054 Color a Tree(贪婪)

    # include <stdio.h> # include <algorithm> # include <string.h> using namespace std ...

  5. $Poj2054\ Color\ a\ Tree\ $ 贪心

    $poj$ $Description$ 一颗树有 $n$ 个节点,这些节点被标号为:$1,2,3…n,$每个节点 $i$ 都有一个权值 $A[i]$. 现在要把这棵树的节点全部染色,染色的规则是: 根 ...

  6. 【POJ 2054】 Color a Tree

    [题目链接] http://poj.org/problem?id=2054 [算法] 贪心 [代码] #include <algorithm> #include <bitset> ...

  7. poj2054 Color a Tree

    神题.这题是巨毒瘤... 自己写真可谓是: 排空驭气奔如电,上天入地求之遍 上穷碧落下黄泉,两处茫茫皆不见 由于我们知道:不是树形时,不停选值最大的节点可以得到最小代价. 那么我们就能想出一个错误的贪 ...

  8. Color a Tree & 排列

    Color a Tree 题目链接 好不可做?可以尝试一下DP贪心网络流.DP 似乎没法做,网络流也不太行,所以试一下贪心. 考虑全局中最大权值的那个点,如果它没父亲,那么一定会先选它:否则,选完它父 ...

  9. Color a Tree[HDU1055]

    Color a Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

随机推荐

  1. React 进阶设计与控制权问题

    控制权--这个概念在编程中至关重要.比如,"轮子"封装层与业务消费层对于控制权的"争夺",就是一个很有意思的话题.这在 React 世界里也不例外.表面上看,我 ...

  2. React Native商城项目实战16 - 购物中心详细页

    逻辑分析: 首页(Home)加载的购物中心组件(ShopCenter),传递url数据: ShopCenter里根据url加载购物中心详细页组件(ShopCenterDetail), ShopCent ...

  3. Oracle Flashback Drop

    Ensure that the prerequisites described in Prerequisites of Flashback Drop are met. The following li ...

  4. nginx 入门 安装

    .yum解决编译nginx所需的依赖包,之后你的nginx就不会报错了 yum install gcc patch libffi-devel python-devel zlib-devel bzip2 ...

  5. sql数据库收缩

    回收步骤: 1.查看日志文件大小[一般回收比较大的] --适用于RDS For SQL Server2012\2016 SELECT DB_NAME(database_id) AS [Database ...

  6. java对接短信平台

    短信验证码目前是比较主流验证身份的一种方式,下面分享下我对接的几种短信平台 阿里云短信:https://api.alidayu.com/docs/api.htm?spm=a3142.7395905.4 ...

  7. 小白学数据分析--聚类分析理论之K-means理论篇

    小白学数据分析--聚类分析理论之K-means理论篇 聚类分析是一类广泛被应用的分析方法,其算法众多,目前像SAS.Splus.SPSS.SPSS Modeler等分析工具均以支持聚类分析,但是如何使 ...

  8. 【ABAP系列】SAP 生产订单完工确认(CO11N) BAPI : BAPI_PRODORDCONF_CREATE_TT

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP 生产订单完工确认(CO1 ...

  9. gradle阿里云镜像配置

    Maven镜像的配置参考: http://blog.java1234.com/blog/articles/252.html buildscript { repositories { mavenLoca ...

  10. 关于Vue的理解以及与React框架的对比

    1.Vue的理解 概念: Vue是一套用于构建用户界面的渐进式框架: Vue的核心库只关注视图层: 是一个数据驱动的MVVM框架: 特性: 确实轻量:体积比较小: 数据绑定简单.方便: 有一些简单的内 ...