zoukankan      html  css  js  c++  java
  • 题解 P2168 【[NOI2015]荷马史诗】

    题目链接

    Solution [NOI2015]荷马史诗

    题目大意:构造(k)叉哈夫曼树

    哈夫曼树


    分析:这题比较模板,可以当做复习初赛(大雾)

    哈夫曼树的定义:

    构造一棵有(n)个节点的(k)叉树,每个节点带有权(w_i),深度(d_i)(规定根深度为(0)),使得(sum w_i imes d_i)最小

    (k=2)时即为合并果子,因此可以想出显而易见的贪心算法,每次从堆中取(k)个合并,但是这样可能根节点的儿子不足(k)个,此时将叶节点移为根节点儿子会使得答案更优

    因此我们需要额外补足一些(w=0)的虚拟点,让儿子不足的情况发生在叶子结点

    每次将(k)个节点合并使得总个数减少(k-1)个,使得(n)个节点合并为(1)个减少了(n-1)个,因此当((k-1) | (n-1))时上述贪心算法正确

    题目还要求代价和最小时最大深度尽量小,权值相同时按照深度排序即可

    #include <cstdio>
    #include <cctype>
    #include <queue>
    using namespace std;
    typedef long long ll;
    inline ll read(){
    	ll x = 0;char c = getchar();
    	while(!isdigit(c))c = getchar();
    	while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    	return x;
    }
    struct HeapNode{
    	ll val;
    	int dep;
    	bool operator < (const HeapNode &rhs)const{
    		return (val == rhs.val) ? (dep > rhs.dep) : val > rhs.val;
    	}
    };
    priority_queue<HeapNode> Q;
    int n,k;
    ll ans1,ans2;
    int main(){
    	n = read(),k = read();
    	for(int i = 1;i <= n;i++)
    		Q.push(HeapNode{read(),0});
    	while((n - 1) % (k - 1))Q.push(HeapNode{0,0}),n++;
    	while(Q.size() != 1){
    		ll add1 = 0,add2 = 0;
    		for(int i = 1;i <= k;i++){
    			HeapNode h = Q.top();Q.pop();
    			add1 += h.val;
    			add2 = max(add2,(ll)h.dep);
    		}
    		ans1 += add1;
    		ans2 = max(ans2,add2 + 1);
    		Q.push(HeapNode{add1,add2 + 1});
    	}
    	printf("%lld
    %lld
    ",ans1,ans2);
    	return 0;
    }
    
  • 相关阅读:
    SD卡性能测试
    在程序内动态获取svn版本号
    在SharePoint 2010程序中使用Session
    图片预读
    CSS图片垂直居中方法整理集合 !(常见问题解答)
    cpld的入门交流之二:秒信号发生器
    基于json数据的jQuery无限级下拉菜单插件
    MySQL 按指定字段自定义列表排序
    10张图让你更了解博客
    IE6 CSS bug: position:relative变成了absolute
  • 原文地址:https://www.cnblogs.com/colazcy/p/11650164.html
Copyright © 2011-2022 走看看