POJ 2054 Color a Tree (贪心)
$ 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 (贪心)的更多相关文章
- POJ 2054 Color a Tree#贪心(难,好题)
题目链接 代码借鉴此博:http://www.cnblogs.com/vongang/archive/2011/08/19/2146070.html 其中关于max{c[fa]/t[fa]}贪心原则, ...
- POJ 2054 Color a Tree
贪心.... Color a Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: ...
- 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 ...
- poj 2054 Color a Tree(贪婪)
# include <stdio.h> # include <algorithm> # include <string.h> using namespace std ...
- $Poj2054\ Color\ a\ Tree\ $ 贪心
$poj$ $Description$ 一颗树有 $n$ 个节点,这些节点被标号为:$1,2,3…n,$每个节点 $i$ 都有一个权值 $A[i]$. 现在要把这棵树的节点全部染色,染色的规则是: 根 ...
- 【POJ 2054】 Color a Tree
[题目链接] http://poj.org/problem?id=2054 [算法] 贪心 [代码] #include <algorithm> #include <bitset> ...
- poj2054 Color a Tree
神题.这题是巨毒瘤... 自己写真可谓是: 排空驭气奔如电,上天入地求之遍 上穷碧落下黄泉,两处茫茫皆不见 由于我们知道:不是树形时,不停选值最大的节点可以得到最小代价. 那么我们就能想出一个错误的贪 ...
- Color a Tree & 排列
Color a Tree 题目链接 好不可做?可以尝试一下DP贪心网络流.DP 似乎没法做,网络流也不太行,所以试一下贪心. 考虑全局中最大权值的那个点,如果它没父亲,那么一定会先选它:否则,选完它父 ...
- Color a Tree[HDU1055]
Color a Tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
随机推荐
- 12 Django组件-form组件
知识预览 forms组件 forms组件 校验字段功能 针对一个实例:注册用户讲解. 模型:models.py class UserInfo(models.Model): name=models.Ch ...
- HDU 5172 GTY's gay friends (线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5172 题意: 给你一个n个数的数组,m次询问,询问在[L, R] 这个区间里面有没有 [1, R-L+ ...
- Prototype js library
Prototype An object-oriented JavaScript framework Prototype is a JavaScript framework that aims to e ...
- curl_init raw传递json参数
protected function curl_vm_record($url, $platform, $authorization, $jsonStr) { $ch = curl_init(); cu ...
- HttpWebRequest、WebClient、RestSharp、HttpClient区别和用途
HttpWebRequest 已经不推荐直接使用了,这已经作为底层机制,不适合业务代码使用,比如写爬虫的时候WebClient 不想为http细节处理而头疼的coder而生,由于内部已经处理了通用设置 ...
- curl 使用 post 请求,传递 json 参数,下载文件
curl -X POST http://ip:8888/nacos/v1/cs/file/download -H "Accept: application/octet-stream" ...
- 阶段1 语言基础+高级_1-3-Java语言高级_02-继承与多态_第2节 抽象类_14-抽象的概念
先来了解什么叫做抽象 父类有个计算面积的方法,但是不同的图形计算面积的方式是不一样的.所以这里的计算面积的方法就是个抽象的方法. 只有到具体的子类里面才能去实现具体的计算面积的方法 动物类是父类.有吃 ...
- delphi如何按照控件的左右顺序来遍历窗体中的每个控件 [问题点数:20 http://bbs.csdn.net/topics/380216822
delphi如何按照控件的左右顺序来遍历窗体中的每个控件delphi默认是按照控件添加进窗体的顺序来遍历的,有没有哪个属性能控制这个/?? 更多0分享到: 对我有用[0] 丢个板砖[0] 引用 | ...
- struts2 基础4 验证器、 国际化
验证器: 验证器:用户输入验证 1.手动编程方式 )对于动作类中所有方法进行验证 a.动作类继承ActionSuport b.覆盖调用public void validate(){} 方法 c.在va ...
- 05.vue-resource的基本使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...