zoukankan      html  css  js  c++  java
  • POJ2054 Color a Tree 贪心

    容易知道,除了根节点之外,下面的儿子节点如果是全树权值最大的点一定会在父亲节点染色之后被染色。

    假如现在有x,y,z三个节点,现在知道x和y的染色是连续的。

    那么先染x,y再染z的代价是x+2y+3z

    如果先z后x和y那么代价是z+2x+3y

    都加上(z-y)后再除以2,就是(x+y)/2+2z和z+(x+y)

    也就是(x+y)/2和z谁先染色的代价

    于是同理可知多个点的合并节点等价代价为sum/点数

    然后不断合并就好了

     1 /* ***********************************************
     2 Author        :BPM136
     3 Created Time  :2018/7/16 11:36:59
     4 File Name     :2054.cpp
     5 ************************************************ */
     6 
     7 #include<iostream>
     8 #include<cstdio>
     9 #include<algorithm>
    10 #include<cstdlib>
    11 #include<cmath>
    12 #include<cstring>
    13 #include<vector>
    14 using namespace std;
    15 
    16 typedef long long ll;
    17 typedef vector<int> VI;
    18 
    19 const int N = 1005;
    20 
    21 int c[N],a[N];
    22 int fa[N];
    23 int n,root;
    24 VI b[N];
    25 bool vis[N];
    26 
    27 int main() {
    28     while(scanf("%d%d",&n,&root)!=EOF) {
    29         if(n==0 && root==0) return 0;
    30         for(int i=1;i<=n;i++) {
    31             scanf("%d",&c[i]);
    32             a[i]=c[i];
    33         }
    34         for(int i=1;i<n;i++) {
    35             int p,f;
    36             scanf("%d%d",&f,&p);
    37             fa[p]=f;
    38         }
    39         for(int i=1;i<=n;i++) {
    40             b[i].clear();
    41             b[i].push_back(i);
    42         }
    43         for(int i=1;i<=n;i++) vis[i]=0;
    44         vis[root]=1;
    45         for(int o=1;o<n;o++) {
    46             int v=0;
    47             double mx=0.0;
    48             for(int i=1;i<=n;i++) if(vis[i]==0) {
    49                 if(a[i]*1.0/b[i].size()>mx) {
    50                     mx=a[i]*1.0/b[i].size();
    51                     v=i;
    52                 }
    53             }
    54             int f=fa[v];
    55             vis[v]=1;
    56             for(int i=0;i<b[v].size();i++) b[f].push_back(b[v][i]);
    57             a[f]+=a[v];
    58             for(int i=1;i<=n;i++) if(vis[i]==0 && fa[i]==v) {
    59                 fa[i]=f;
    60             }
    61         }
    62         ll ans=0;
    63         for(int i=0;i<b[root].size();i++) ans+=(long long)(i+1)*c[ b[root][i] ];
    64         printf("%lld
    ",ans);
    65     }
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    西藏之行的一点总结
    《吃的法则》总结
    《心法》总结
    分布式系统中的CAP、ACID、BASE概念
    《你当像鸟飞往你的山》总结
    《怪诞行为学》总结
    编程的一些抽象核心
    《活法》总结
    Mac使用Charles给iPhone抓包流程
    《认知天性》总结
  • 原文地址:https://www.cnblogs.com/MyGirlfriends/p/9317040.html
Copyright © 2011-2022 走看看