ZOJ3715 Kindergarten Election(贪心,模拟)

题目:




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 ≤ 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
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.


Author:  OUYANG, Jialin
Contest:  The 10th Zhejiang Provincial Collegiate Programming Contest
Submit     Status
思路:

这个题的题意很难懂。。

有t组数据,接下来一个n,代表有几个人,接下来一行有n-1个数据,代表2号到第n号给谁投票了,接下来一行又有n-1个数据,代表了你要贿赂从2号到n号的投票人所需要的钱数(贿赂的作用是可以改变投票的结果是本来给别人投的票投给自己,但是自己不能给自己投票),现在1号想当这一群人的老大,那么他要获得最大的票数,所以他要花钱贿赂,题目问的是最少需要话费多少钱才可以使1号成为老大。。

以第一组样例来解释一下:


2//两组数据
4//一共四个人
1 1 2//2-->1,3-->1,4-->2(二号投票给1号,三号投票给1号,4号投票给二号)
1 10 100//要贿赂2,3,4号所花费的钱数分别是1,10,100


注释写的很详细,具体看注释

代码:

#include <cstdio>
#include <cstring>
#include <cctype>
#include <string>
#include <set>
#include <iostream>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define N 1000+20
#define mod 10007
#define M 1000000+10
#define LL long long
using namespace std;
int num1[N];
int num[N];//记录得票的数量
int vis[N];//标记是否被贿赂
struct node
{
    int v,w;
} g[N];
bool cmp(node a,node b)
{
    return a.w<b.w;//按照贿赂的价格从小到大排序
}
int main()
{
    int t,n;
    cin>>t;
    while(t--)
    {
        mem(num,0);
        mem(g,0);
        cin>>n;
        for(int i=1; i<n; i++)
        {
            cin>>g[i].v;//投票给第几个人
            num[g[i].v]++;//给对应的人记录票数
        }
        for(int i=1; i<n; i++)
        {
            cin>>g[i].w;//贿赂投票的人的价格
        }
        sort(g+1,g+n,cmp);
        int minn=inf;//初始化要求的值
        int sum;
        for(int i=num[1]; i<n; i++)//枚举第一个人所有可能获得的投票数
        {
            mem(vis,0);//所有人都没被贿赂
            memcpy(num1,num,sizeof(num));//把num数组赋值给num1数组
            int flag_num=num1[1];//记录当前第一个人所获得的票数
            sum=0;
            for(int j=1; j<n; j++)//枚举投票人
            {
                if(g[j].v!=1&&num1[g[j].v]>=i)//如果第j个人投得票的目标不是1,且被投票的人的票数还大于当前枚举的票数
                {
                    num1[g[j].v]--;//开始贿赂,让投票人改投
                    flag_num++;//当前的得票数+1
                    vis[j]=1;//标记一下这个人已经被贿赂了
                    sum+=g[j].w;//记录贿赂所花的钱数
                }
            }
            if(flag_num<=i)//经过第一轮贿赂之后所得的票数还没有到当前枚举的票数
            {
                for(int j=1;j<n&&flag_num<i; j++)//重新枚举投票人且当前得到的票数不超过当前枚举的票数
                {
                    if(vis[j]==0&&g[j].v!=1)//当没有被标记且这个人投票的目标不是1
                    {
                        num1[g[j].v]--;//贿赂
                        flag_num++;//得票数+1
                        vis[j]=1;//标记
                        sum+=g[j].w;//记录贿赂所花的钱数
                    }
                }
                int j=2;
                for(; j<=n&&num1[j]>=i; j++);//找一下1号当前的票数是不是最大的
                if(j!=n+1)
                    minn=min(minn,sum);//如果是最大的,那么更新一下话费的钱数
            }
        }
        cout<<minn<<endl;
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值