HDU1055Color a Tree
Posted nsd-email0820
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU1055Color a Tree相关的知识,希望对你有一定的参考价值。
题意
给一棵树,要给树上每一个结点染色,第i 个结点染色需要代价为:t * w[i] (t 表示i 结点是第几个染色的),还有一个前提是:要给i 结点染色,必须先给i 结点的父结点染色(根结点随便染)
分析
lyd蓝书 p41例题
贪心,奇特的均分权值。
就分两种情况,若以该节点的父节点全部被涂过,且该节点是剩的最大权值的节点,则涂。
如果父节点没有被涂过,它一定会紧接着父节点涂了之后马上涂,所以和父节点均分节点权值(包括乘的 t 后的权值),以此类推,对于整棵树进行这样的操作,直到所有节点均分一个权值(所有节点被染色)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define N 1010 int fa[N],f[N],vis[N]; int n,r,t,x,fax; long long ans; struct email { int sum,num; double w; }a[N]; inline int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } inline int getmax() { int p=-1; double maxx=0; for(int i=1;i<=n;i++) { if(!vis[i]&&maxx<a[i].w) maxx=a[i].w,p=i; } return p; } int main() { while(scanf("%d%d",&n,&r)&&n) { for(int i=1;i<=n;i++) { int val; scanf("%d",&val); fa[i]=i;vis[i]=0; a[i].num=1;a[i].sum=val; a[i].w=1.0*a[i].sum/a[i].num; } for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); f[v]=u; } t=1;ans=0;vis[0]=1;f[r]=0; while(1) { x=getmax(); if(x==-1)break; fax=find(f[x]); if(vis[fax]) { ans+=a[x].sum*t; t+=a[x].num; vis[x]=1; } else { ans+=a[x].sum*a[fax].num; a[fax].num+=a[x].num; a[fax].sum+=a[x].sum; a[fax].w=1.0*a[fax].sum/a[fax].num; vis[x]=1;fa[x]=fax; } } printf("%lld ",ans); } return 0; }
以上是关于HDU1055Color a Tree的主要内容,如果未能解决你的问题,请参考以下文章
HDU - 6241 :Color a Tree(不错的二分)