一个班有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; }
时间: 2024-10-06 08:30:21