$ 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. WCF - Hosting WCF Service 四种托管方式

    https://www.tutorialspoint.com/wcf/wcf_hosting_service.htm After creating a WCF service, the next st ...

  2. nodeName,nodeValue未知 xml 入库方案 The ElementTree iterparse Function

    import xml.etree.ElementTree as ET from lxml.html import * from xmljson import badgerfish as bf from ...

  3. Django学习之视图

    一.Django的View(视图) 1.一个简单的视图 3.CBV和FBV 4.给视图加装饰器 使用装饰器装饰FBV 使用装饰器装饰CBV 二.Request对象和Response对象 1.reque ...

  4. 疑难杂症——bash: /dev/null: Permission denied

    描述 在使用 Devstack 的时候需要时常切换用户su stack,此时会触发错误: root@mickeyfan-dev:~# su stack bash: /dev/null: Permiss ...

  5. 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_01 Collection集合_2_集合框架介绍

  6. 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_04 数据结构_1_数据结构_栈

    2.1 数据结构有什么用? 当你用着java里面的容器类很爽的时候,你有没有想过,怎么ArrayList就像一个无限扩充的数组,也好像链表之类 的.好用吗?好用,这就是数据结构的用处,只不过你在不知不 ...

  7. javascript 跳出循环比较

    for continue 跳出当前循环,继续下一个循环 break 结束循环 forEach 不能使用continue , break return/return false 跳出当前循环,在forE ...

  8. try...catch语句

    程序的异常:Throwable 严重问题Error我们不处理,这种问题一般都是很严重的,比如内存溢出 问题Exception 编译期问题不是RuntimeException的异常必须进行处理,如果不处 ...

  9. struts2 基础

    框架(frameWork):某一种应用的半成品 struts2: 表现层 处理与页面进行交互的相关功能  hibernate: 持久层 负责业务逻辑数据的持久化  spring: 业务层 负责复杂的业 ...

  10. vue—两个数组,去重相同项