标签:枚举 贪心 zoj brute force
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.
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.
For each test case, print the minimal cost of candies to help Sheldon become the ONLY leader.
2 4 1 1 2 1 10 100 3 3 2 1 10
0 11
In the first case,
题意:在幼儿园里,每个小朋友投一票选举领导(不能投自己),得票最多的小朋友成为领导(若有多个则有多个领导)..现在有个小朋友(编号为1)想当唯一的领导,于是准备贿赂一些小朋友,让他们把票投给自己,买通第i个人需要花费c[i]个糖果.问这个小朋友最少用多少的糖可以使得他成为唯一的领导。
解题思路:首先枚举一号小朋友投票的人,然后枚举其要成为领导所需的票数x,需要贿赂d=x-cnt[i]个人,如果2到n号小朋友有某个i票数不小于x,那么需要贿赂投i的人(按照代价从小到大的顺序贿赂),使其票数小于x,每贿赂一个人d减小1,若d<0,那么枚举失败,需要增加x,如果d为正数那么只需要在没有贿赂的人当中选d个代价最小的进行贿赂即可。
代码如下:
#include <iostream> #include <cstring> #include <algorithm> #include <vector> using namespace std; typedef long long ll; const int maxn = 1e2 + 10; int c[maxn],f[maxn],cnt[maxn],n; bool used[maxn]; bool cmp(const int & a,const int & b) { return c[a]<c[b]; } int main(int argc, char const *argv[]) { int T; cin>>T; while(T--) { cin>>n; memset(cnt,0,sizeof cnt); vector<int>sa,v[maxn];//sa保存不选1的人,v[i]保存投i的人 for(int i=2;i<=n;i++) { cin>>f[i]; cnt[f[i]]++; if(f[i]!=1) { sa.push_back(i); v[f[i]].push_back(i); } } for(int i=2;i<=n;i++)cin>>c[i]; for(int i=2;i<=n;i++)sort(v[i].begin(), v[i].end(),cmp);//对选i的人按贿赂代价排序 sort(sa.begin(), sa.end(),cmp);//对没选1的人按贿赂代价排序 int ans=1e9; for(int vote=2;vote<=n;vote++) {//枚举1号投的人 cnt[vote]++; for(int x=cnt[1];x<n;x++) {//枚举1号最后所需票数 memset(used,0,sizeof used); int d=x-cnt[1],w=0; for(int i=2;i<=n;i++) {//检查是否成功 if(cnt[i]<x)continue; int t=cnt[i]; for(int j=0;j<v[i].size();j++) { t--; w+=c[v[i][j]]; used[v[i][j]]=1; d--; if(t<x||d<=0)break; } if(t>=x||d<0){ w=1e9; d=0; break; } } if(d>0) { for(int i=0;d&&i<sa.size();i++)if(!used[sa[i]]) { w+=c[sa[i]]; d--; } } ans=min(ans,w);//更新代价 } cnt[vote]--; } cout<<ans<<endl; } return 0; }
ZOJ 3715 Kindergarten Election(枚举+贪心)
标签:枚举 贪心 zoj brute force
原文地址:http://blog.csdn.net/acvcla/article/details/42030427