1. 程式人生 > >BZOJ4198或UOJ130 荷馬史詩 【K叉哈夫曼樹】【堆】

BZOJ4198或UOJ130 荷馬史詩 【K叉哈夫曼樹】【堆】

題解:
用一個堆來維護一個K叉哈夫曼樹,如果無法合併(即n-1不為k-1的倍數時),就補充n-k個虛擬節點,節點的權值為0(不會影響結果),再合併即可。

程式碼:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

typedef long long LL;

const int inf = 1 << 26;

struct trees {
    LL v, h;
};

bool
operator<(trees a, trees b){ if(a.v != b.v) return a.v > b.v; return a.h > b.h; } priority_queue<trees> q; int n, k; int main(){ scanf("%d %d", &n, &k); for ( int i = 1; i <= n; i ++ ) { trees a; scanf("%lld", &a.v); a.h = 1
; q.push(a); } LL top = 0; if((n-1)%(k-1) != 0) top += k-1-(n-1)%(k-1); // 需要補為 0 的結點的個數 for ( int i = 1; i <= top; i ++ ) { trees need; need.v = 0; need.h = 1; q.push(need); } top += n; LL ans = 0; while(top != 1) { trees a; LL temp = 0
, mx = 0; for ( int i = 1; i <= k; i ++ ) { a = q.top(); temp += a.v; mx = max(mx, a.h); q.pop(); } ans += temp; a.v = temp; a.h = mx+1; q.push(a); top -= k-1; } printf("%lld\n%lld\n", ans, q.top().h-1); return 0; }