补题向 | Elections(枚举)

C. Elections

m个政党,n个人投票,可以用钱收买投票者(话说,题出得这么现实真的大丈夫?),求使得政党1获胜的最少费用

如果某个政党i票数太多,1政党可以通过买除i之外的政党的票,最终比i票多获胜,也可以买原本投给i的票,一方面增加1的票数,另一方面减少i的票数

计算1政党如果最终有k张票,为了获胜,其他政党的票数必须比k小,则某个政党i至少要卖掉vn[i]-k张票,如果至少其他政党要卖的票数多于1政党为了得到k张票要买的票数,那么说明如果1政党最终只有k张票是不可能获胜的,否则就买下其他政党至少要卖的票(挑最便宜的买,先排好序),买完这些票之后就保证了其他政党的票都少于k,接下来只要挑便宜的票买够k张

枚举1政党最终有k(vn[1]~m)张票能获胜所需金额,输出最小值

#include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<fstream>
#include<math.h>
#include<stack>
#include<queue>
#include<bitset>
#include<utility>
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const double eps=0.0000000000001;
const ll mod=4294967296;
const ll M=1000000000;
int n,m;
struct V{
	int i;
	int q;
};
vector<V> v;//记录投票者编号和金额,用于排序 
vector<V> p[3005];//p[i]:记录投给i政党的投票者编号和金额 
int vn[3005];//vn[i]:投给政党i的票数 
bool f[3005];//f[i]:值为1表示i投票者已经被收买了 
bool cmp(V x,V y){
	return x.q<y.q;
}
ll cal(int k){
	//1政党要得到k票获胜要花费的金额 
	vector<V> t;
	memset(f,0,sizeof(f));
	ll res=0;
	for(int i=2;i<=m;i++){
		int num=vn[i];
		for(int j=0;j<num;j++){
			if(num-j>=k){
				t.push_back(p[i][j]);//i政党要卖掉(j+1)票,票数才会比k小 
			}
			else break;
		}
	}
	if(t.size()>k-vn[1]){
		return -1;//如果其他政党至少要卖的票多于1政党要买的票,则1政党不可能获胜 
	}
	sort(t.begin(),t.end(),cmp);
	int pos=0;
	int ki=vn[1];
	while(ki<k&&pos<t.size()){
		res+=t[pos].q;
		f[t[pos].i]=1;
		pos++;
		ki++;
	} 
		for(int j=0;j<v.size();j++){
			if(ki>=k)break;
			if(f[v[j].i]==0){
				f[v[j].i]=1;
				res+=v[j].q;
				ki++;
			}
		}//买完其他政党至少需要卖的票,再从金额少且没被买的票里买 
	return res;
}

int main(){
	scanf("%d%d",&n,&m);
	int a,b;
	memset(vn,0,sizeof(vn));
	V t;
	for(int i=1;i<=n;i++){
		scanf("%d%d",&a,&b);		
		if(a!=1){
			t.i=i;
			t.q=b;
			v.push_back(t);
			p[a].push_back(t);
		}
		vn[a]++;
	}
	sort(v.begin(),v.end(),cmp);//所有金额从小到大排序 
	for(int i=2;i<=m;i++){
		sort(p[i].begin(),p[i].end(),cmp);
		//除了1之外的政党的票的金额排序 
	}
	ll ans=INF;
	for(int i=vn[1];i<=n;i++){
		ll res=cal(i);
		if(res==-1)continue;
		else ans=min(ans,res);	
	}
	printf("%I64d\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/bekote/article/details/81750785
今日推荐