标签:上班 res pre 开始 const min turn clear bsp
一个班有n个小朋友,要选一个班长,(n>=3),每个人不能投自己,给出每个人想要选的人,1号小朋友相当班长,如果一个小朋友不选自己
那么,自己可以给他bi个糖果让他选自己,那么请输出,最少花费多少个糖果 ,1号小朋友可以当上班长
开始的做法是贪心小的,那么问题很复杂,直接枚举小的是不符合条件的
后来想,枚举一号小朋友最后的票为k,那么其他人的票肯定小于等于k-1,如果有小朋友的选票高于k-1,那么先把投这个人的所有小朋友贿赂到小于k-1,按照需要的糖果数量
如果这个时候的选票大于k了,那么显然这个k不符合条件,如果等于k,那么用现在的花费更新答案,如果小于k,那么再从不选自己的小朋友中挑选需要糖果最少的,补足k张票
直接贪心无法做,那么通过枚举一个值,那么减少条件,从而能贪心
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int a[maxn],b[maxn];
vector<int> g[maxn];
int main(){
int t,n,m;
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<maxn;i++)
g[i].clear();
for(int i=2;i<=n;i++)cin>>a[i];
for(int i=2;i<=n;i++)cin>>b[i],g[a[i]].push_back(b[i]);
int ans=INT_MAX;
for(int i=1;i<=n;i++)sort(g[i].begin(),g[i].end());
int hhh=g[1].size();
if(hhh<1)
hhh=1;
for(int k=hhh;k<=n;k++){
int res=0;
int cnt=g[1].size();
priority_queue<int,vector<int>,greater<int> > q;
while (!q.empty()) q.pop();
for(int i=2;i<=n;i++){
int j=0;
if(g[i].size()>=k){
for(;j<g[i].size()-k+1;j++){
res+=g[i][j],cnt++;
}
}
for(;j<g[i].size();j++)q.push(g[i][j]);
}
if(cnt>k)
continue;
while(cnt<k){
cnt++;
res+=q.top();
q.pop();
}
ans=min(ans,res);
}
cout<<ans<<endl;
}
return 0;
}
zoj 3715 K - Kindergarten Election
标签:上班 res pre 开始 const min turn clear bsp
原文地址:http://www.cnblogs.com/jihe/p/6715391.html