poj解题报告——2054
来源:互联网 发布:php分类信息网源码 编辑:程序博客网 时间:2024/06/10 04:45
处理思路:利用贪心思想,每次取权值最大的节点,不断的将权值最大节点与它的父节点合并。
过程:
1、初始时将序列中的time[i]都置为1,w[i]置为c[i];
2、查找最大的w[i], 返回其位置;
3、将该位置的c[ ]与它的父节点c[ ]合并(合并过程就是C_i / T_i,C_i = c[该节点] + c[父节点],T_i = time[该节点]+time[父节点])得到新的父节点w[](w[父节点] = C_i / T_i),如果有节点与pos相连,让它指向pos的父节点;
4、重复2、3,知道合并完;
至于如何求出结果:初始时使ans = sum(c[i]);每次查找到一个最大权值,ans += c[i] * time[父节点];
代码如下
#include <stdio.h>#define N 1007struct node{ int t; int p; int c; double w;}num[N];int n, r;int find(){ int pos,i; double max=0; for(i=1;i<=n;i++) if(num[i].w>max&&i!=r) { max=num[i].w; pos=i; } return pos;}void main(){ int i,j,a,b,pos,ans,f; while(scanf("%d%d",&n,&r),n||r) { ans=0; for(i=1;i<=n;i++) { scanf("%d",&num[i].c); num[i].w =num[i].c; num[i].t=1; ans+=num[i].c; } for(i=1;i<n;i++) { scanf("%d%d",&a,&b); num[b].p=a; } i=n; while(i>1) { pos=find(); num[pos].w=0; f=num[pos].p; ans+=num[pos].c*num[f].t; for(j=1;j<=n;j++) if(num[j].p==pos) num[j].p=f; num[f].c+=num[pos].c; num[f].t+=num[pos].t; num[f].w=(double)num[f].c/num[f].t; i--; } printf("%d\n",ans); }}
0 0
- poj解题报告——2054
- POJ 1088 滑雪——解题报告
- POJ 1047——解题报告
- poj解题报告——poj1006
- poj解题报告——1032
- poj解题报告——1061
- poj解题报告——1450
- poj解题报告——1002
- poj解题报告——2109
- poj解题报告——1218
- poj解题报告——1250
- poj解题报告——1012
- poj解题报告——3299
- poj解题报告——2209
- poj解题报告——2406
- poj解题报告——2242
- poj解题报告——1401
- poj解题报告——1328
- Intellij_idea_14快捷键
- PAT1044
- Java 关于两个集合合并,并排序的demo
- DataGridView在vb.net中的操作技巧
- word2vec代码注释
- poj解题报告——2054
- ios 中正则表达式
- C# VS2010 无法切换输入法。
- 删除数据库中的所有视图的sql脚本文件生成
- Activity Fragments
- zoj 1221 && poj 1603 Risk
- Java多线程练习二
- Git Cheat Sheet Chinese
- 数据结构和算法学习系列之最大子序列求和问题的O(N)时间复杂度