首页 > 代码库 > zoj 3715 K - Kindergarten Election

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;}

  

zoj 3715 K - Kindergarten Election