2017组队训练 ZOJ

来源:互联网 发布:厦门市网络预约 编辑:程序博客网 时间:2024/06/05 08:01

点击一下:https://vjudge.net/problem/38590/origin

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 ≤ nfi ≠ 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
241 1 21 10 10033 21 10
Sample Output
011
题目大意:

班里有n个人,进行投票选班长,每个人都投出一票且不能投自己。而且班里有一个规则,每个人都有一个贿赂费,就是我某个人可以给他想要的贿赂费,那么这个人就会投给你。现在1号相当班长,即他的票数必须大于每个人的才行,问最少要花的贿赂费。

题解:

这个题当时没做出来,也想到是贪心了枚举了,但是处理的时候复杂了。想一想该以谁为中心贪心,如果是直接找最小的花费进行贪心的话是不可能的,因为还有票数的限制。那么枚举1号所得的票数进行贪心,就是当1号的票数为k时要最少贿赂的钱数或者不能实现票数为k 的情况。这是可以实现的。还有一个问题就是1号的票投给谁了,当1号得票数为k时,这时在不记录1号所投票的时候其他人必须至少存在一个人的票数是小于k-1的,这样才能保证1号的票投出去使得1号所得的票仍然最大。(但是有的人并没有考虑这个情况也过了!!!!!)

#include <iostream>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <vector>#define INF 0x3f3f3f3fusing namespace std;vector<int>v[300];int a[1000],c[1000];int main(){    int t;    scanf("%d",&t);    int n;    while(t--)    {        scanf("%d",&n);        for(int i=0; i<=n+2; i++)v[i].clear();        int lead=0;        for(int i=2; i<=n; i++)        {            scanf("%d",&a[i]);        }        for(int i=2; i<=n; i++)        {            scanf("%d",&c[i]);            v[a[i]].push_back(c[i]);///记录每一个人的投他票的人的贿赂费用        }        for(int i=2; i<=n; i++)        {            sort(v[i].begin(),v[i].end());///贿赂费用排序        }        lead=v[1].size();        int ans=INF;        for(int k=1; k<=n; k++)        {            int ant=lead;            int cost=0;            priority_queue<int,vector<int> ,greater<int > >q;///把所有没有贿赂剩下的的人的贿赂费存起来,以便票数不够时从费用小的贿赂            while(!q.empty())q.pop();            for(int j=2; j<=n; j++)            {                int len=v[j].size();                int i=0;                if(len>=k)///枚举的当前的票数k<=其他人的得票数的时候,就贿赂投j这个人票的人,让j这个人的票数小于k                {                    for(;i<len-k+1; i++)                    {                        cost+=v[j][i];                        ant++;                    }                }                for(; i<len; i++)q.push(v[j][i]);///没有贿赂剩下的            }            if(ant>k)continue;            else if(ant==k)            {                ///必须存在票数<k-1的,因为还有1的一票                int flag=0;                for(int j=2; j<=n; j++)                {                    int len=v[j].size();                    if(len<k-1)                    {                        flag=1;                        break;                    }                }                if(!flag)                {                    ant++;                    int x=q.top();                    q.pop();                    cost+=x;                }                if(ant==k)                    ans=min(ans,cost);                else continue;            }            else            {                for(int i=0; i<k-ant; i++)                {                    int x=q.top();                    q.pop();                    cost+=x;                }                ans=min(ans,cost);            }        }        printf("%d\n",ans);    }    return 0;}



0 0
原创粉丝点击