ZOJ-3715-Kindergarten Election

在学期开始的幼儿园,n个小孩(1到n)在课堂上需要选择他们的新领导。

第一个孩子会投票给他最好的朋友fi(其中1≤fi≤n,这太可惜了,自己投票,所以fi≠i)。 

获得最多票数的孩子将是领袖。 如果有一个以上的孩子获得最多的票数,在新学期将有多个领导人。

小谢尔顿(下标为1)想成为唯一的领导者。 (这意味着他得到的票数应该严格大于任何其他。)

如果他给ci糖果给第i个孩子,第i个孩子会认为谢尔顿作为新的最好的朋友,当然投票谢尔顿。

请帮助谢尔顿成为唯一的领导者,最低的糖果成本。 顺便说一下,谢尔顿应该投票支持自己想要的任何一个人。


枚举获胜所需要的票数,从其他超过该票数的中买票(当然从便宜的开始买),如果买完后还不够枚举的票数就买其他没有买过的票.

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <queue>
#include <vector>
#include <math.h>
#include <stack>
#include <map>
#define rtl rt<<1
#define rtr rt<<1|1
typedef long long LL;
using namespace std;
const int MAX = 15000+10;
const double eps = 1e-10;
const double PI = acos(-1.0);
int t, n, f[MAX], c[MAX], ans, ant, num, num0;
bool vis[MAX];
struct node
{
    int c, id;
};
bool operator < (node a, node b)
{
    if(a.c!=b.c)return a.c>b.c;
    return a.id<b.id;
}
priority_queue<node>que[MAX], que2[MAX], qq, qqq;
int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);
        for(int i = 1; i<=n; ++i)
            while(!que[i].empty())que[i].pop();
        while(!qq.empty())qq.pop();
        for(int i = 2; i<=n; ++i)
            cin>>f[i];
        num0 = 0;
        for(int i = 2; i<=n; ++i)
        {
            node ver;
            scanf("%d", &ver.c);
            ver.id = i;
            if(f[i]!=1)
            {
                que[f[i]].push(ver);
                qq.push(ver);
            }
            else num0++;
        }
        ans = 0x7fffffff;
        for(int i = max(2, (int)que[1].size()); i<=n; ++i)
        {
            num = num0;
            ant = 0;
            memset(vis, 0, sizeof(vis));
            for(int j = 2; j<=n; ++j)
            {
                que2[j] = que[j];
                while((int)que2[j].size()>i-1)
                {
                    node ver = que2[j].top();
                    que2[j].pop();
                    ant+=ver.c;
                    vis[ver.id] = 1;
                    num++;
                }
                if(num>i)break;
            }
            if(num<i)
            {
                qqq = qq;
                while(num<i)
                {
                    node ver = qqq.top();
                    qqq.pop();
                    if(!vis[ver.id])
                    {
                        ant+=ver.c;
                        num++;
                    }
                }
            }
            if(num==i)ans = min(ans, ant);
        }
        if(ans==0x7fffffff)ans = 0;
        cout<<ans<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值