您的位置:首页 > 其它

hdu 1055 poj 2054 映射二叉堆

2013-05-10 19:23 260 查看
算法:

算法证明:http://hi.baidu.com/cheezer94/item/7b4a15214b2050022b0f1c0a

代码来源:http://www.cppblog.com/notonlysuccess/archive/2009/07/02/88793.html

ò 1.标记根节点为第一个访问的节点。

ò 2.求出当前未访问节点中的最大点权节点i。

ò 3.将i和它的父亲j合并为一个节点,节点权值为两者权值的算术平均数。在序列P中将j的后继置为i。同时更新树的信息。

ò 4.若当前树中节点数大于1,则转第2步。

ò 5.树的大小为1时算法结束。

ò 6.扫描求得的P序列得到答案。

ò 时间复杂度:O(N^2)。期望得分50-70分。

#include "stdio.h"
#include "string"
#define maxn 1001
struct H{
int val;
int cost;
int time;
void clear() {
val = cost = time = 0;
}
}hh[maxn];
int father[maxn];
int main() {
int n,r,i;
while(scanf("%d%d",&n,&r),n+r) {
for(i =1 ; i <= n ; i ++) {
scanf("%d",&hh[i].cost);
hh[i].val = hh[i].cost;
hh[i].time = 1;
}
for(i = 1; i < n ; i ++) {
int a,b;
scanf("%d%d",&a,&b);
father[b] = a;
}
while(true) {
int idx = 0;
for(i = 1 ; i <= n ; i ++) {
if(i != r && hh[i].time && (idx == 0 || hh[idx].val * hh[i].time < hh[i].val * hh[idx].time)) {
idx = i;
}
}
if(idx == 0)    break;
int f = father[idx];
hh[f].cost += hh[idx].cost + hh[idx].val * hh[f].time;
hh[f].val += hh[idx].val;
hh[f].time += hh[idx].time;
hh[idx].clear();
}
printf("%d\n",hh[r].cost);
}
return 0;
}


(使用映射二叉堆)

ò 注意到我们每次操作需要得到当前最大权对应的节点i并将i的儿子的父亲改为i的父亲。

ò O(N)的扫描成为算法复杂度的瓶颈。

ò 如何高效求最大值?

ò 推荐数据结构:最大堆(O(LogN))。

ò 如何高效地将i的儿子的父亲改为i的父亲?

ò 推荐数据结构:并查集(O(α(N)))。

ò 总的时间复杂度:O(NLogN)。期望得分100分。

注意根不能放到堆中!

#include "stdio.h"
#include "string"
#define maxn 1001
//-----------------------Binary Heap------------------------------------
struct Heap {
int val,cost,time,idx;
}hh[maxn];
int pos[maxn];
int len;
bool Prior(Heap a,Heap b) {
return a.val * b.time > b.val * a.time;
}
void Push(Heap s) {
int i;
for(i = ++len ; i > 1 && Prior(s,hh[i/2]); i /= 2) {
hh[i] = hh[i/2];
pos[hh[i].idx] = i;
}
hh[i] = s;
pos[hh[i].idx] = i;
}
Heap Pop(int idx) {
if(idx == -1)    return hh[0];
Heap ret = hh[idx];
Heap last = hh[len--];
int i,s;
for(i = idx ; i * 2 <= len; i = s) {
s = i * 2;
if(s + 1 <= len && Prior(hh[s+1],hh[s])) {
s ++;
}
if(Prior(hh[s],last)) {
hh[i] = hh[s];
pos[hh[i].idx] = i;
} else {
break;
}
}
hh[i] = last;
pos[hh[i].idx] = i;
for(i = idx ; i > 1 && Prior(hh[i],hh[i/2]); i /= 2) {
Heap buf = hh[i];
hh[i] = hh[i/2];
hh[i/2] = buf;
pos[hh[i].idx] = i;
pos[hh[i/2].idx] = i/2;
}
return ret;
}
//---------------------------------------------------------------
int father[maxn];
int main() {
int n,r,i;
hh[0].cost = hh[0].time = hh[0].val = 0;
while(scanf("%d%d",&n,&r),n+r) {
len = 0;
Heap root;
for(i =1 ; i <= n ; i ++) {
Heap buf;
scanf("%d",&buf.cost);
buf.val = buf.cost;
buf.time = 1;
buf.idx = i;
if(i == r) {
root = buf;
} else {
Push(buf);
}
}
for(i = 1 ; i < n ; i ++) {
int a,b;
scanf("%d%d",&a,&b);
father[b] = a;
}
while(len) {
Heap max = Pop(1);
int f = father[max.idx];
if(f == r) {
root.cost += max.cost + max.val * root.time;
root.time += max.time;
root.val += max.val;
} else {
Heap fa = Pop(pos[f]);
fa.cost += max.cost + max.val * fa.time;
fa.time += max.time;
fa.val += max.val;
fa.idx = f;
Push(fa);
}
pos[max.idx] = -1;
}
printf("%d\n",root.cost);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: