BZOJ 4198 荷马史诗

Posted on 2016-09-05 20:05  ziliuziliu  阅读(156)  评论(0编辑  收藏  举报

哈夫曼树。

如果要最大的深度最小,再按h排序即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxv 100500
#define maxe 1000500
using namespace std;
long long n,k,val[maxv*5],nume=0,g[maxv*5],tot,sum=0,dis[maxv*5],fath[maxv*5];
struct edge
{
    long long v,nxt;
}e[maxe];
struct status
{
    long long val,pnt,h;
};
bool operator <(status x,status y)
{
    if (x.val!=y.val) return x.val>y.val;
    return x.h>y.h;
}
priority_queue <status> q;
void addedge(long long u,long long v)
{
    e[++nume].v=v;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void dfs(long long x)
{
    for (long long i=g[x];i;i=e[i].nxt)
    {
        long long v=e[i].v;
        if (v!=fath[x])
        {
            fath[v]=x;dis[v]=dis[x]+1;
            dfs(v);
        }
    }
}
int max(int a,int b)
{
    if (a>b) return a;
    return b;
}
int main()
{
    scanf("%lld%lld",&n,&k);
    for (long long i=1;i<=n;i++)
    {
        scanf("%lld",&val[i]);
        status s;
        s.pnt=i;s.val=val[i];s.h=0;
        q.push(s);
    }
    long long ret=0;
    while ((n+ret-1)%(k-1)!=0) ret++;
    for (long long i=1;i<=ret;i++)
    {
        status s;
        s.pnt=n+i;s.val=0;s.h=0;
        q.push(s);
        val[n+i]=0;
    }
    n+=ret;tot=n;
    long long ret1=0,ret2=0;
    while (q.size()>1)
    {
        sum=0;tot++;int mx=0;
        for (long long i=1;i<=k;i++)
        {
            status b=q.top();q.pop();
            sum+=b.val;mx=max(mx,b.h);
            addedge(b.pnt,tot);addedge(tot,b.pnt);
        }
        status s;
        s.pnt=tot;s.val=sum;s.h=mx+1;q.push(s);
        ret2=max(ret2,s.h);
        val[tot]=0;
    }
    dfs(tot);
    for (long long i=1;i<=n;i++)
        ret1+=val[i]*dis[i];
    printf("%lld\n%lld\n",ret1,ret2);
    return 0;
}