$ 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. 从Java 调用JavaScript

    篇幅过长 下载资源链接https://www.slidestalk.com/s/java_javascript_5hl09w

  2. 如何删除由Automater创建的服务

    想要设置两个实用的快捷设置(如何设置): 1.复制当前文件或者文件夹路径 2.在终端打开文件夹 然后想到可以用mac自带的自动操作这款软件,英文叫Automater.接着发现,显示路径栏后,直接就提供 ...

  3. picker-view组件

    picker-view组件,是一个页面上的滚动选择器: 如果想进行滚动:他的子元素必须是  picker-view-column  组件: picker-view-column组件:只是提供了一个可视 ...

  4. Wowza 4 vod 录播多层目录无法播放问题

    找到一个解决方案,但是无法下载zip包 https://stackoverflow.com/questions/21303361/how-to-stream-mp4-files-from-subdir ...

  5. qbzt day3 上午

    内容提要 堆 lca(最近公共祖先) st表 hash 并查集 树状数组 线段树 数据结构 1.堆 Priority_queue 他滋兹:插入删除查询最大值(最小值) 分为大根堆小根堆 2.LCA 首 ...

  6. 浅释Functor、Applicative与Monad

    引言 转入Scala一段时间以来,理解Functor.Applicative和Monad等概念,一直是我感到头疼的部分.虽然读过<Functors, Applicatives, And Mona ...

  7. Win32InputBox,C接口的,实现类似VB的InputBox的功能

    #ifndef __03022006__WIN32INPUTBOX__ #define __03022006__WIN32INPUTBOX__ /* This library is (c) Elias ...

  8. Node.js 的环境配置

    1.安装node.js 官网上面最新版本的nodejs 都是自带npm的.http://nodejs.cn/至于安装过程选择默认下载就行 2.安装淘宝镜像,也就是将国外的一些资源代理到国内. 步骤:1 ...

  9. json-server-----》基本使用

    [WangQi]---json-server---基本使用   一.前后端并行开发的痛点 前端需要等待后端开发完接口以后 再根据接口来完成前端的业务逻辑 二.解决方法 在本地模拟后端接口用来测试前端效 ...

  10. Netty实战之性能调优与设计模式

    设计模式在Netty 中的应用(回顾): 单例模式要点回顾: 一个类在任何情况下只有一个对象,并提供一个全局访问点. 可延迟创建. 避免线程安全问题. 在我们利用netty自带的容器来管理客户端链接的 ...