枚举加二分找最优解Kindergarten Election

题址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3715

Kindergarten Election

Time Limit: 2 Seconds      Memory Limit: 65536 KB

At the beginning of the semester in kindergarten, the n little kids (indexed from 1 to n, for convenience) in class need to elect their new leader.

The ith kid will vote for his best friend fi (where 1 ≤ fi ≤ n, and it's too shame to vote for yourself, so fi ≠ i). And the kid who gets the most votes will be the leader. If more than one kids who get the largest number of votes, there will be multiple leaders in the new semester.

Little Sheldon (the kid with index 1) is extremely vain, and he would like to be the ONLY leader. (That means the number of votes he gets should strictly larger than any other.) Soon Sheldon found that if he give ci candies to the ith kid, the ith kid would regard Sheldon as the new best friend, and of course vote for Sheldon.

Every kid including Sheldon loves candies. As an evil programmer, please help the evil Sheldon become the ONLY leader with minimum cost of candies. By the way, Sheldon should vote for any one he wants EXCEPT himself.

Input

There are multiple test cases. The first line of input contains an integer T (T ≤ 100) indicating the number of test cases. Then T test cases follow.

The first line of each case contains one integer: n (3 ≤ n ≤ 100) -- the number of kids in class.

The second line contains n-1 integers: fi (1 ≤ fi ≤ n, fi ≠ i, and 2 ≤ i ≤ n) -- represents that the best friend of ith kid is indexed with fi.

The third line contains n-1 integers: ci (1 ≤ ci 1000, and 2 ≤ i ≤ n) -- represents that if Sheldon gave ci candies to the ith kid, the ith kid would vote Sheldon, instead of their old best friend fi, as the new semester leader.

Output

For each test case, print the minimal cost of candies to help Sheldon become the ONLY leader.

Sample Input
2
4
1 1 2
1 10 100
3
3 2
1 10
Sample Output
0
11
Hint

In the first case,

  • If Sheldon vote for 2nd kid, the 2nd kid and Sheldon will both have 2 votes. In this case, Sheldon have to pay 100 candies to the 4th kid, and get 3 votes to win;
  • If Sheldon vote for 3rd or 4th kid, Sheldon will win with 2 votes without sacrifice any candy. 
题意:有一些小朋友要选领导者,总共有n个人,每人有一票,现在给出了每个人 (除了第一个小朋友) 都投票给谁。现在第一个小朋友想当领导者,他可以贿赂其他小朋友(使这个小朋友把票投给他), 给出每个小朋友 除了第一个小朋友 )被贿赂需要的棒棒糖数量;他所得的票数必须是最高的(不能并列),现在求他最少需要多少棒棒糖才能当领导者。

思路:因为最多有100个小朋友,最多有100票,所以可以枚举所有情况+贪心;
假设他自己以k票获胜,求最少棒棒糖,设ans=1000000存最小值;
k票获胜,所以其他大于k票的人   必须把支持他的人贿赂成支持自己的(使他只剩k-1票),保证k票最高, 贿赂这些小朋友肯定挑棒棒糖少的(贪心);当把所有大于k票的都解决以后。现在自己的票数s为  刚开始有的+贿赂过来的,
如果s<k;说明票数不够k,要从剩下的小朋友当中贿赂一些(贪心,挑棒棒糖最少的),使自己票数刚好为k票。所用棒棒糖数若小于ans,则更新ans。
如果s==k,直接于ans比较;
如果s>k,说明贿赂的票有多余了,所以一定不会是最优解,直接舍去这种情况。
设刚开始他的得票数为x,则for(int k=max(2,x);k<=n;k++) 把k可能值枚举一遍;
最后的ans一定是最优解;
还有一点刚开始我不明白的地方,说明一下:你们会不会想到    如果他把自己的一票投给任何一个人(除了他自己)时,万一让那个人和自己票数相同怎么办。他肯定会把票投给其他小朋友(票最少的那一个)。除非其他小朋友的票数全部相等且都是k-1票(随便投一个他都只能是并列第一)(0.0),每个小朋友最多有一票,所以以上特例每个人都有k-1票,k-1=0;或者k-1=1;(只有这两种情况,因为 每个小朋友最多有一票 解得k=0或k=1;题中给出小朋友数量最少为3个,所以他至少要有2票才能赢,所以
k=max(2,x);k是一定大于等于2的,所以就不用考虑自己的那一票了。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#include<string>
#define LL long long int
#define inf 0x3f3f3f3f
#define N 1000010
using namespace std;
struct node
{
    int c,f;
} a[105],b[105];
int cnt[105],c[105],n,book[105];
int cmp(node ll,node rr)
{
    return ll.c<rr.c;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        memset(cnt,0,sizeof(cnt));
        for(int i=2; i<=n; i++)
        {
            scanf("%d",&a[i].f);
            cnt[a[i].f]++;
        }
        for(int i=2; i<=n; i++)
            scanf("%d",&a[i].c);
            int ans=inf;
        for(int k=max(2,cnt[1]); k<=n; k++)
        {
            memset(book,0,sizeof(book));
            int sum=cnt[1],tans=0;
            for(int i=2; i<=n; i++)
            {
                if(cnt[i]>=k)
                {
                    sum+=cnt[i]-k+1;
                    if(sum>k)break;
                    int len=1;
                    for(int j=2; j<=n; j++)
                    {
                        if(a[j].f==i) b[len].c=a[j].c,b[len++].f=j;
                    }
                    sort(b+1,b+len,cmp);
                    for(int j=1;j<=cnt[i]-k+1;j++)
                    {
                        tans+=b[j].c;
                        book[b[j].f]=1;
                    }
                }
            }
            if(sum>k) continue;
            int len=1;
            for(int i=2;i<=n;i++)
            {
                if(!book[i]&&a[i].f!=1)c[len++]=a[i].c;
            }
            sort(c+1,c+len);
            for(int i=1;i<=k-sum;i++)
            {
                tans+=c[i];
            }
            ans=min(ans,tans);
        }
         printf("%d\n",ans);
    }
}
第一次接触枚举答案的题,也是看题解想了好久的;
http://blog.csdn.net/xiangaccepted/article/details/69665618;
这道题是类似的,二分答案找最优解。

















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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值