• poj2054 Color a Tree ****


      1 /*
    2 * POJ-2054 color a tree
    3 *
    4 * 贪心 难题!
    5 *
    6 * 思路1:
    7 * http://hi.baidu.com/cheezer94/blog/item/d98eca065202a2f237d122da.html
    8 * 思路2:
    9 * http://www.cnblogs.com/X-Kly/archive/2011/11/02/POJ2054.html
    10 * 代码:
    11 * http://xinbaolianmeng.com/showshouye.aspx?type=7&ID=110
    12 *
    13 * 简单讲:
    14 * 每次找到 权值最大的“集合”, 与其“父集合”合并, 权值为 两个集合中 顶点权值的平均。
    15 * 直到只剩一个集合
    16 *
    17 *
    18 * 下面有范例代码, 一样, 可看其注释
    19 *
    20 *
    21 */
    22
    23
    24 #include <cstdio>
    25 using namespace std;
    26
    27 const int maxn = 1000 + 5;
    28
    29 int n, r;
    30 int c[maxn], fa[maxn];
    31 int pre[maxn], next[maxn], sum[maxn], num[maxn];
    32 bool vis[maxn];
    33
    34 int find_max(){
    35 double max = -1;
    36 int maxNum = -1;
    37 for(int i=1; i<=n; i++){
    38 if(!vis[i] && (sum[i] * 1.0 / num[i]) > max){
    39 max = (sum[i] * 1.0 / num[i]);
    40 maxNum = i;
    41 }
    42 }
    43 return maxNum;
    44 }
    45
    46
    47 void unionFa(int x){
    48 int faSet;
    49 for(faSet=fa[x]; pre[faSet]!=-1; faSet = pre[faSet]);
    50 sum[faSet] += sum[x];
    51 num[faSet] += num[x];
    52 for(faSet=fa[x]; next[faSet]!=-1; faSet = next[faSet]);
    53 next[faSet] = x;
    54 pre[x] = faSet;
    55
    56 vis[x] = 1;
    57 }
    58
    59 int main(){
    60 while(scanf("%d%d", &n, &r)){
    61 if(n == 0) return 0;
    62
    63 for(int i=1; i<=n; i++){ //注意从1开始!!(因为输入的根、边的标号都是从1开始的)
    64 scanf("%d", &c[i]);
    65 sum[i] = c[i];
    66 num[i] = 1;
    67 pre[i] = next[i] = -1;
    68 vis[i] = false;
    69 }
    70
    71 int u, v;
    72 for(int i=1; i<n; i++){
    73 scanf("%d%d", &u, &v);
    74 fa[v] = u;
    75 }
    76
    77 int d;
    78 vis[r] = 1;
    79 while(1){
    80 d = find_max();
    81 if(d == -1) break;
    82 unionFa(d);
    83 }
    84
    85 int ans = 0, t = 1;
    86 for(int i=r; i!=-1; i=next[i]){
    87 ans += t * c[i];
    88 t++;
    89 }
    90 printf("%d\n", ans);
    91 }
    92
    93
    94 return 0;
    95 }
    96
    97 /* ===================== 范例程序 有注释 ================================
    98
    99 #include<iostream>
    100   #include <cstdio>
    101 using namespace std;
    102 const int max_n=1010;
    103 int pre[max_n];//pre[i]用来表示当前集合(包含i)的上个元素
    104 int next[max_n];//next[i]用来表示当前集合(包含i)的下个元素
    105 int c[max_n];
    106 int num[max_n];//num[i]表示当前集合(包含i)的元素个数
    107 int visit[max_n];
    108 int sum[max_n];//当前集合元素和
    109 int father[max_n];//father[i]表示i的父元素
    110 int n,r;
    111 int find_max()//找到当前权值最大的集合,合并后的点当做一个集合,也就是一个点
    112 {
    113 double max=0;
    114 int bh=-1;
    115 for(int i=1;i<=n;i++)
    116 {
    117 if(max<(sum[i]*1.0)/num[i]&&visit[i]==0)
    118 {
    119 max=(sum[i]*1.0)/num[i];
    120 bh=i;
    121 }
    122 }
    123 return bh;
    124 }
    125 void uni(int x)//联合
    126 {
    127 int i;
    128 for(i = father[x]; pre[i] != -1; i = pre[i]);//找到父元素所在的集合
    129 sum[i]+=sum[x];
    130 num[i]+=num[x];
    131 for(i = father[x]; next[i] != -1; i = next[i]);//找到父元素所在集合的底元素
    132 next[i]=x;
    133 pre[x]=i;
    134 visit[x]=1;
    135 }
    136 int main()
    137 {
    138
    139 while(scanf("%d %d",&n,&r),n&&r)
    140 {
    141 for(int i=1;i<=n;i++)
    142 {
    143 scanf("%d",&c[i]);
    144 sum[i]=c[i];
    145 visit[i] =0;
    146 pre[i] = next[i] = -1;
    147 num[i] = 1;
    148 }
    149 for(int i = 1; i < n; i++)
    150 {
    151 int a, b;
    152 scanf("%d %d", &a, &b);
    153 father[b] = a;
    154 }
    155
    156 int d;
    157 visit[r]=1;
    158 while(1)
    159 {
    160 d=find_max();
    161 if(d==-1)break;
    162 uni(d);
    163 }
    164 int ans=0,tjq=1;
    165 for(int i=r;i!=-1;i=next[i])
    166 {
    167 ans+=tjq*c[i];
    168 tjq++;
    169 }
    170 printf("%d\n",ans);
    171 }
    172
    173 return 0;
    174 }
    175
    176 */
  • 相关阅读:
    「2017 山东三轮集训 Day1」Flair
    Luogu P4321 随机漫游
    「WC2018」通道
    「CTSC2018」暴力写挂
    关于二项式相乘
    BZOJ #3625 CF #438E 小朋友和二叉树
    GIS可视化
    微信小程序Promise对象
    SQL Server-执行计划教会我如何创建索引
    IIS+NGINX 负载web服务器
  • 原文地址:https://www.cnblogs.com/longdouhzt/p/2390554.html
Copyright © 2020-2023  润新知