- 1000ms 内存限制:
- 65535kB
-
构造一个具有n个外部节点的扩充二叉树,每个外部节点Ki有一个Wi对应,作为该外部节点的权。使得这个扩充二叉树的叶节点带权外部路径长度总和最小:
Min( W1 * L1 + W2 * L2 + W3 * L3 + … + Wn * Ln)
Wi:每个节点的权值。
Li:根节点到第i个外部叶子节点的距离。
编程计算最小外部路径长度总和。
输入
-
第一行输入一个整数t,代表测试数据的组数。
对于每组测试数据,第一行输入一个整数n,外部节点的个数。第二行输入n个整数,代表各个外部节点的权值。
2<=N<=100
输出
- 输出最小外部路径长度总和。 样例输入
-
231 2 341 1 3 5
样例输出
-
917
提示
-
仅考查huffman树的建立,数据范围小,可以不需要使用堆结构.
不过鼓励使用第一题实现的堆来寻找最小和次小元素。
-
总时间限制:
-
描述
优先队列用堆实现。
这题曾RE十几次。。只因用的全局变量没有初始化。。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<assert.h>
#include<ctype.h>
#include<stdlib.h>
using namespace std;
struct node{
int huffman;
struct node *l,*r;
}a[300],b[220];///b节点数组用来保存 a节点数组原来的值。
int n,fu,sum;
void siftdown( int wz )///wz是下标的意思。 这里的操作是如果此节点比子节点的权大的话,就交换 直到找到合适的位置为止
{
if(wz>n)return ;
int twz = wz;
node temp = a[twz];
int j = 2*wz;
while(j <= n )
{
if( j+1 <= n && a[j].huffman > a[j+1].huffman )j++;///左孩子比右孩子大。J + 1
if(temp.huffman > a[j].huffman )///找到合适位置。
{
a[twz] = a[j];
twz = j;
j = j*2;
}
else break;
}
a[twz] = temp;
}
void siftup( int wz )///向上调整 子节点比父节点小的话。
{
int twz = wz;
node temp = a[wz];
while( twz > 1 && a[twz/2].huffman > temp.huffman )
{
a[twz] = a[twz/2];
twz /= 2;
}
a[twz] = temp;
}
void build( )///建堆 由下往上建堆。。由下标大的往上。。由孙子到祖宗,课程说这样建堆比较好。具体原因 望你分析给我听。
{
int i;
for(i = n/2+1; i >0; i--)
siftdown(i);
for(i = n/2+1;i > 1;i--)
siftdown(i);
}
void del(int wz)///删除堆中最小的节点。 也就是根。删除方法是 拿这个完全二叉树的最后一个节点替换掉根 再向下调整。
{
if(n<=1)return ;
a[1] = a[n--];
siftdown(1);
}
node jianshu( node a1,node a2 )///建huffman树。又是静态拼装。。想请教怎么动态。。看有个视频运用链表。。指针的指针。。= -
{
b[fu++] = a1;
b[fu++] = a2;
node temp;
temp.l = &b[fu-2];
temp.r = &b[fu-1];
temp.huffman = a1.huffman + a2.huffman;
return temp;
}
/*void vis(int a,int level)
{
printf("%d_____%d_))((\n",a,level);
}*/
void bianli(node *T,int level)///遍历 计算最小外部路径和。
{
if(T)
{
if(!T->l&&!T->r)sum += (level) *(T->huffman);
//vis(T->huffman,level);
bianli(T->l,level+1);
bianli(T->r,level+1);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
fu=1;
sum = 0;
scanf("%d",&n);
int i;
for(i= 1; i <= n; i++)///初始化。
{
scanf("%d",&a[i].huffman);
a[i].l = a[i].r = NULL;
}
build();
int tme = n-1;///拼装的次数。
while(tme--)
{
if(n>=3&&a[2].huffman>a[3].huffman){node temp= a[2];a[2] = a[3]; a[3] = temp;}
if(n>=2)a[2] = jianshu(a[1],a[2]);
del(1);
build();
}
bianli(&a[1],0);
printf("%d\n",sum);
}
return 0;
}