枚举加二分找最优解Kindergarten Election

来源:互联网 发布:浙江省政府数据平台 编辑:程序博客网 时间:2024/06/05 19:22

题址: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, then 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 friendfi (where 1 ≤ fi ≤ n, and it's too shame to vote for yourself, sofi ≠ 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 theONLY leader. (That means the number of votes he gets should strictly larger than any other.) Soon Sheldon found that if he giveci 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 theONLY leader with minimum cost of candies. By the way, Sheldon should vote for any one he wantsEXCEPT himself.

Input

There are multiple test cases. The first line of input contains an integerT (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 withfi.

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

Output

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

Sample Input

241 1 21 10 10033 21 10

Sample Output

011

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 1000010using 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
原创粉丝点击