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;
    }
    
  • 相关阅读:
    数组以字符串记录(字符串转数组)
    linux下OpenSSL的RSA密钥生成
    php rsa加密解密实例 及签名验证-自己实践
    php rsa加密解密实例
    PHP的openssl加密扩展使用小结
    支付宝开放平台 配置RSA(SHA1)密钥 OpenSSL配置公钥私钥对
    HTTP缓存控制
    java去任意范围的随机数
    (转)Eclipse4.2 Tomcat启动报错 A child container failed during start
    模态框事件介绍
  • 原文地址:https://www.cnblogs.com/colazcy/p/11650164.html
Copyright © 2011-2022 走看看