ZOJ - 3715 Kindergarten Election 暴力+贪心

题目链接:点击查看

题目:一共n个人投票,每个人最初有投票的对象和贿赂这个人需要的话费,求要想第一个人得票最多的最小话费

题解:枚举第一个人的得票数,首先大于这个票数的都要投给一,先让话费小的给1,其他的都放到优先队列中,然后最后若票数还不够,那就在继续给第一个人

#include<bits/stdc++.h>
using namespace std;
vector<int> v[110];
int n;
int id[110];
struct node{
	int w;
	node(int w_)
	{
		w=w_;
	}
	bool operator <(const node &xx)const 
	{
		return w>xx.w;
	}
};
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		scanf("%d",&n);
		for(int i=2;i<=n;i++)
		{
			scanf("%d",&id[i]);
			
		}
		for(int i=1;i<=n;i++) v[i].clear();
		int x;
		for(int i=2;i<=n;i++)
		{
			scanf("%d",&x);
			v[id[i]].push_back(x);
		}
		for(int i=2;i<=n;i++) sort(v[i].begin(),v[i].end());
		priority_queue<node> q;
		int ans=1e9;
		int cnt;
		int len,cn;
		for(int i=n;i>=2;i--)
		{
			cnt=v[1].size();
			cn=0;
			while(!q.empty())q.pop();
			for(int j=2;j<=n;j++)
			{
				len=v[j].size();
				for(int k=0;k<max(len-i+1,0);k++)
					cnt++,cn+=v[j][k];
				for(int k=max(len-i+1,0);k<len;k++)
				{
					q.push(node(v[j][k]));
				}		
			}
			while(cnt<i && !q.empty())
			{
				cnt++;
				node now=q.top();q.pop();
				cn+=now.w; 
			}
			if(cnt>=i)
			{
				ans=min(ans,cn);
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/mmk27_word/article/details/88879612