• Color a tree


    Solution

    众所周知这是一道dl贪心

    Step 1

    如果没有先后染色的顺序让你去染色,你肯定会先把最大的节点先染了,但是如果有了限制,类似的,就会把子节点中最大的点先染了,所以两个操作会是连续的。

    所以假设待染色的点分别为 x,y,z ,其中 x,y 已知是连续染色,则只有两种染法

    1.x+2y+3z1.x+2y+3z 先染 x,y ,再染 z

    2.z+2x+3y2.z+2x+3y 先染 z ,再染 x,y

    比较两数大小, 1-2=-x-y+2z

    也就是比较

    (x+y)/2 

    也就启发我们运用平均值作为性价比,每次扫描一遍求出最大性价比进行染色,将这一个点放在父亲节点中最后一个点之后马上染色,直到最后将整棵树缩成一个点,得到最终答案

    Step 2

    #include<bits/stdc++.h>
    using namespace std;
    int n,r,ans;
    struct node{int c,fa,t;double w;}num[1005];
    int find(){//求出最大性价比
        int mbi;
        double maxn=0;
        for(int i=1;i<=n;i++)
         if(i!=r&&num[i].w>maxn)
          maxn=num[i].w,mbi=i;
        return mbi;
    } 
    int main(){
        while(scanf("%d %d",&n,&r)&&n&&r){
            ans=0;
            for(int i=1;i<=n;i++)scanf("%d",&num[i].c),ans+=num[i].c,num[i].t=1,num[i].fa=0,num[i].w=num[i].c;//预处理清空
            for(int i=1,a,b;i<n;i++)scanf("%d %d",&a,&b),num[b].fa=a;
            for(int i=1;i<n;i++){
                int tmp=find();
                num[tmp].w=0;
                int f=num[tmp].fa;
                ans+=num[tmp].c*num[f].t;//合并性价比最大的节点,在父亲的节点之后紧跟着被染色
                for(int j=1;j<=n;j++)
                 if(num[j].fa==tmp)
                  num[j].fa=f;//合并
                num[f].t+=num[tmp].t;//更新父亲节点
                num[f].c+=num[tmp].c;
                num[f].w=(double)(num[f].c)/num[f].t;
            }
            printf("%d
    ",ans);//输出
        }
    }
  • 相关阅读:
    Learning_the_bash_Shell_Third_Edition 15/n
    Learning_the_bash_Shell_Third_Edition 14/n
    Learning_the_bash_Shell_Third_Edition 13/n
    cvb源码分析,resful规范,drf,drf序列化组件,95
    rest_framework登录组件,权限组件
    forms组件
    分页器
    基于ajax提交数据
    回顾django内容
    多表操作
  • 原文地址:https://www.cnblogs.com/coder-cjh/p/11581375.html
Copyright © 2020-2023  润新知