题目链接:点击查看
题目:一共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;
}