hdu 5242 (优先队列贪心+瞎搞)

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int t,n,m,fa[maxn];
ll val[maxn];
set<int>a[maxn];
void DFS(int u,int father)
{
    set<int>::iterator it;
    int sum=a[u].size(),tm;
    for(it=a[u].begin();it!=a[u].end();it++)
    {
        int v=*it;
        if(v==father)
        {
            tm=v;
            continue;
        }
        fa[v]=u;
        if((sum==2&&u!=1)||(sum==1&&u==1))
        {
            val[v]+=val[u];
            val[u]=0;
           // fa[v]=fa[u];
        }
        DFS(v,u);
    }
    a[u].erase(tm);
}
struct node{
    int x;
    ll val;
    node(int _x,ll _val)
    {
        x=_x;
        val=_val;
    }
    bool operator < (const node &a)const
    {
        return val>a.val;
    }
};
void solve(int x)
{
    int y=x;
    x=fa[x];
    val[y]=0;
    while(a[x].size()==1)
    {
        val[x]=0;
        y=x;
        x=fa[x];
    }

    a[x].erase(y);
    val[y]=0;
    while(a[x].size()==1)
    {
        set<int>::iterator it=a[x].begin();
        int v=*it;
        val[v]+=val[x];
        val[x]=0;
        x=v;
    }
}
priority_queue<node>q;
int main()
{
    //cout << "Hello world!" << endl;
    //freopen("in.txt","r",stdin);
    scanf("%d",&t);
    int cas=0;
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            a[i].clear();
            scanf("%lld",&val[i]);
        }
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            a[x].insert(y);
            a[y].insert(x);
        }

        DFS(1,0);
        int tmp=0;
        while(!q.empty()) q.pop();
        for(int i=1;i<=n;i++)
        {
            if(a[i].size()==0)
            {
                tmp++;
                q.push(node(i,val[i]));
            }
        }
        m=max(0,tmp-m);
        while(!q.empty()&&m>0)
        {
            node fuck=q.top();
            q.pop();
            int u=fuck.x;
            if(val[u]!=fuck.val)
            {
                fuck.val=val[u];
                q.push(fuck);
                continue;
            }
            m--;
            solve(u);
        }
        ll ans=0;
        for(int i=1;i<=n;i++)
        ans+=val[i];
        printf("Case #%d: %lld\n",++cas,ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值