CF1019A Elections
可能是晚上脑子瓦特了,我居然没有想出来。。。
题目大意:
有n个人,m个政党,每个人刚开始支持的政党是pi,你可以贿赂他ci元钱,改变他支持的政党
问你至少要花费多少使得1号政党当选。当选是要求改政党的得票严格高于其他政党
题解:
枚举一号政党当选是的选票,然后贪心
设每个政党的选票是a[i]
也就是凡是选票多余枚举数量的政党,最便宜的便收买a[1]-a[i]个人,如果收买的人数多余枚举数,显然不行
如果还不够,就在其他没有被收买的人中买最便宜的满足条件的人
注意要判断当前方案是否可行,别用set,会多一个log
# include<iostream> # include<algorithm> # include<queue> # include<cstdio> # include<cmath> # include<vector> # include<cstring> using namespace std; typedef long long LL; const int mn = 3005; bool vis[mn]; int n,m; vector<pair<int,int> > s[mn]; vector<pair<int,int> > a; LL ans=3*1e12 + 5; int main() { int x,y; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d%d",&x,&y); s[x].push_back(make_pair(y,i)); if(x!=1) a.push_back(make_pair(y,i)); } sort(a.begin(),a.end()); int tmp=s[1].size(),N=a.size(); for(int i=1;i<=m;i++) { if(s[i].size()>=tmp) sort(s[i].begin(),s[i].end()); } for(int i=0;i<=n-tmp;i++) { // printf("%d\n",i); bool flag=true; int ret=0; long long cost=0; memset(vis,0,sizeof(vis)); for(int j=2;j<=m;j++) { int k=s[j].size(); if(k>=tmp+i) { if(k-(tmp+i)+1+ret>i) {flag=false;break;} ret+=k-(tmp+i)+1; for(int ss=0;ss<k-(tmp+i)+1;ss++) { cost+=s[j][ss].first; vis[s[j][ss].second]=1; } } } if(!flag) continue; /*for(int j=0;j<i-ret;j++) cost+=a[j];*/ if(i!=ret) { int j=0,k=0; while(1) { if(j==N) { flag=false; break; } if(!vis[a[j].second]) { cost+=a[j].first;k++; if(k==i-ret) break; } j++; } } //printf("%d %d\n",i,cost); if(flag) ans=min(ans,cost); } printf("%I64d",ans); return 0; }