zoj 3715 K - Kindergarten Election

一个班有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;
}

  

posted @ 2017-04-15 19:38  N维解析几何  阅读(342)  评论(0编辑  收藏  举报