poj2054(贪心)

来源:互联网 发布:斗战神帐号淘宝 编辑:程序博客网 时间:2024/06/06 21:43
题意:有一棵树,每个节点都有一个代价基值Ci。现在要给每个点染色,第一个染根节点,其余的节点染色的时候其父节点必须已染色。每个节点染色会用掉一个时间单位,每个节点染色的代价是染完此节点时的总时间T*Ci。问染完全部节点所需要的最小代价。


解法:这道题真的略吊,不过最终我还是看了网上的题解才会做的。每次基值最大的节点一定会是在父节点染完色后马上进行染色的,然后可以假想此节点就可以和父节点合体为一个节点。这个时候基值就变成了合体中的平均值(证明略仔细想想可以想明白)。这个算法大概就是个贪心,有点像克鲁斯卡尔求最小生成树那样,一块一块解决,最后全部归一就解决了整个问题。由于自己写的有点麻烦,wa了几发,还是太弱了,继续学习。。。


发一个对这道题解释很好的一个博客:http://www.cnblogs.com/yu-chao/archive/2012/02/19/2358565.html


我的代码:
#include <iostream>#include <stdio.h>#include <cstring>#include <vector>#include <queue>using namespace std;struct edge{    int v,next;} edges[100000];int head[1010];int count1=0;void addedge(int u,int v){    edges[count1].v=v;    edges[count1].next=head[u];    head[u]=count1++;}double num[1010];int mount[1010];int parent[1010];bool rem[1010];struct point{  double stan;  int order;};bool operator<(point a,point b){    return a.stan<b.stan;}priority_queue<point> que;int root;int n;int main(){   while(scanf("%d%d",&n,&root)==2)   {       while(!que.empty())        que.pop();       if(n==0&&root==0)        break;       double ans=0;       count1=0;       memset(head,-1,sizeof head);       memset(rem,0,sizeof rem);       for(int i=1;i<=n;i++)       {           mount[i]=1;       scanf("%lf",num+i);       point p;p.stan=num[i];p.order=i;       que.push(p);       }       for(int i=0;i<n-1;i++)       {           int a,b;           scanf("%d%d",&a,&b);           parent[b]=a;           addedge(a,b);       }       for(int i=0;i<n-1;i++)       {           while(rem[que.top().order]||que.top().order==root)            que.pop();           point p=que.top();           que.pop();           int pre=parent[p.order];           ans+=p.stan*mount[p.order]*mount[pre];           for(int i=head[p.order];i!=-1;i=edges[i].next)           {               int a=edges[i].v;               parent[a]=parent[p.order];               addedge(parent[p.order],a);           }           rem[p.order]=1;           point tool;tool.order=parent[p.order];           tool.stan=double(p.stan*mount[p.order]+num[pre]*mount[pre])/double(mount[p.order]                    +mount[pre]);           num[pre]=tool.stan;mount[pre]+=mount[p.order];           que.push(tool);       }       printf("%.0f\n",ans+mount[root]*num[root]);   }    return 0;}/*5 11 2 1 2 41 21 32 43 53 11 1 31 21 34 11 1 1 11 22 33 4*/

0 0
原创粉丝点击