• poj2054 Color a Tree


    神题。这题是巨毒瘤...

    自己写真可谓是:

    排空驭气奔如电,上天入地求之遍

    上穷碧落下黄泉,两处茫茫皆不见

    由于我们知道:不是树形时,不停选值最大的节点可以得到最小代价。

    那么我们就能想出一个错误的贪心:每次从能选的中选出最大的。

    下面我们来构造反例:


          root

       ↙     ↘

     1         2

    100


    贪心:2 + 2 + 300 = 304

    实际:1 + 200 + 6 = 207

    那么我们该如何处理呢?

    完全搞不倒啊!看题解看题解

    得出如下结论:最大的节点一定是紧随着父节点染色的。

    下一步:没有下一步....?????

    我们要把这两个节点合并!

    等效权值为平均数!

    很遗恨的是,我只会证明两个点时权值是平均数。更多的还有待考证...

    不过做题就是要靠想象!这就是正确的!

    所以我们在代码实现的难题上继续败北......

    我的想法是每个节点记录所有子节点以及所有合并过来的节点的顺序。用两个vector来实现。

    然后那个堆是最困扰我的地方,实现起来困难重重。

    看一看标程:cnm!直接n²暴力!

    1000 * 1000 ......我觉得还行

    然后我还发现了一件事:它没有记录次序!合并的同时更新ans!

    惊为天人!

    代码要简洁高效。这一点在寒假时我就有体会,现在又有这种感觉。

     1 /**
     2 poj 2054
     3 */
     4 #include <cstdio>
     5 using namespace std;
     6 typedef long long LL;
     7 const int N = 1010;
     8 const double eps = 1e-10;
     9 
    10 struct Node {
    11     int tot, n, fa;
    12     bool del;
    13     double val;
    14 }node[N];
    15 
    16 int n, R;
    17 
    18 inline int find() {
    19     double maxval = -1;
    20     int ans = 0;
    21     for(int i = 1; i <= n; i++) {
    22         if(!node[i].del && i != R && node[i].val - maxval > eps) {
    23             maxval = node[i].val;
    24             ans = i;
    25         }
    26     }
    27     return ans;
    28 }
    29 
    30 inline int getfa(int k) {
    31     while(node[k].del) {
    32         k = node[k].fa;
    33     }
    34     return k;
    35 }
    36 
    37 int main() {
    38     scanf("%d%d", &n, &R);
    39     while(n || R) {
    40         LL ans = 0;
    41         node[R].fa = 0;
    42         for(int i = 1; i <= n; i++) {
    43             scanf("%d", &node[i].tot);
    44             node[i].val = (double)node[i].tot;
    45             node[i].n = 1;
    46             node[i].del = 0;
    47             ans += node[i].tot;
    48         }
    49         for(int i = 1; i < n; i++) {
    50             int x, y;
    51             scanf("%d%d", &x, &y);
    52             node[y].fa = x;
    53         }
    54         //printf("
    ");
    55         for(int i = 1; i < n; i++) {
    56             int s = find();
    57             int f = getfa(node[s].fa);
    58             //printf("%d %d
    ", s, f);
    59             ans += node[f].n * node[s].tot;
    60             node[f].n += node[s].n;
    61             node[f].tot += node[s].tot;
    62             node[f].val = (double)(node[f].tot) / node[f].n;
    63             //printf("%f
    ", node[f].val);
    64             node[s].del = 1;
    65         }
    66         printf("%I64d
    ", ans);
    67         scanf("%d%d", &n, &R);
    68     }
    69     return 0;
    70 }
    AC代码
  • 相关阅读:
    R语言用神经网络改进Nelson-Siegel模型拟合收益率曲线分析
    用R语言用Nelson Siegel和线性插值模型对债券价格和收益率建模
    R语言LME4混合效应模型研究教师的受欢迎程度
    R语言Black Scholes和Cox-Ross-Rubinstein期权定价模型案例
    R语言中的Nelson-Siegel模型在汇率预测的应用
    R语言中的block Gibbs吉布斯采样贝叶斯多元线性回归
    LNMP搭建
    php高性能开发阅读笔记
    php 关于经纬度距离计算方法
    在已经部署svn 服务器上,搭建svn项目 成功版
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/9029150.html
Copyright © 2020-2023  润新知