77 lines
1.4 KiB
C++
77 lines
1.4 KiB
C++
#include <iostream>
|
||
#include <queue>
|
||
#include <vector>
|
||
|
||
using namespace std;
|
||
|
||
/*
|
||
Huffman 树节点
|
||
在竞赛中一般不需要真的建树,只关心权值
|
||
*/
|
||
struct Node {
|
||
long long w; // 当前节点权值
|
||
|
||
Node(long long _w) : w(_w) {}
|
||
};
|
||
|
||
/*
|
||
priority_queue 默认是大根堆
|
||
这里通过重载比较函数,使其变为小根堆
|
||
*/
|
||
struct cmp {
|
||
bool operator()(const Node& a, const Node& b) const {
|
||
return a.w > b.w; // 权值小的优先
|
||
}
|
||
};
|
||
|
||
int main() {
|
||
ios::sync_with_stdio(false);
|
||
cin.tie(nullptr);
|
||
|
||
int n;
|
||
cin >> n;
|
||
|
||
/*
|
||
优先队列(小根堆)
|
||
每次可以 O(log n) 取出最小的两个权值
|
||
*/
|
||
priority_queue<Node, vector<Node>, cmp> pq;
|
||
|
||
// 读入 n 个权值
|
||
for (int i = 0; i < n; i++) {
|
||
long long x;
|
||
cin >> x;
|
||
pq.push(Node(x));
|
||
}
|
||
|
||
/*
|
||
特判:只有一个节点
|
||
WPL = 0(没有边)
|
||
*/
|
||
if (n == 1) {
|
||
cout << 0 << '\n';
|
||
return 0;
|
||
}
|
||
|
||
long long WPL = 0;
|
||
|
||
/*
|
||
Huffman 树构造过程
|
||
每次取最小的两个合并
|
||
*/
|
||
while (pq.size() > 1) {
|
||
Node a = pq.top(); pq.pop();
|
||
Node b = pq.top(); pq.pop();
|
||
|
||
long long mergedWeight = a.w + b.w;
|
||
WPL += mergedWeight;
|
||
|
||
pq.push(Node(mergedWeight));
|
||
}
|
||
|
||
// 输出带权路径长度
|
||
cout << WPL << '\n';
|
||
|
||
return 0;
|
||
}
|