POJ2054 Color a Tree 贪心
Posted mygirlfriends
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于POJ2054 Color a Tree 贪心的主要内容,如果未能解决你的问题,请参考以下文章