题意:
n个人投票 唯一一个票数最多的人当选 1想当选 他可以通过给别人糖让不选他的人选他 问 最少需要多少糖
思路:
由于n比较小 可以枚举1当选时得了多少票 这样就可以贪心的使用糖
如果1当选时有i票 那么所有人都要先保证选票数<i 而且还要保证至少一个人<i-1 因为1还会投出一票
保证上述条件下 如果1票数已经超过i 则说明这次枚举是失败的 如果不到i 就尽量少用糖补到i
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define M 110
int t,n,ans,tot;
int vot[M],get[M],vis[M];
struct node
{
int cost,to,use;
bool operator<(const node ff) const
{
return cost<ff.cost;
}
}nd[M];
int main()
{
int i,j,k,tmp;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(get,0,sizeof(get));
ans=2147483647;
tot=0;
for(i=2;i<=n;i++)
{
scanf("%d",&vot[i]);
get[vot[i]]++;
}
for(i=2;i<=n;i++)
{
scanf("%d",&nd[tot].cost);
if(vot[i]==1) continue;
nd[tot].to=vot[i];
nd[tot].use=0;
tot++;
}
sort(nd,nd+tot);
for(i=get[1];i<=n;i++)
{
tmp=0;
memcpy(vis,get,sizeof(int)*(n+1));
for(j=0;j<tot;j++)
{
if(vis[nd[j].to]>=i)
{
nd[j].use=1;
tmp+=nd[j].cost;
vis[nd[j].to]--;
vis[1]++;
}
}
for(j=0;j<tot&&vis[1]<i;j++)
{
if(!nd[j].use)
{
nd[j].use=1;
tmp+=nd[j].cost;
vis[nd[j].to]--;
vis[1]++;
}
}
for(j=2;j<=n;j++)
{
if(vis[j]<i-1) break;
}
if(j<=n&&vis[1]==i) ans=min(ans,tmp);
for(j=0;j<tot;j++) nd[j].use=0;
}
printf("%d\n",ans);
}
return 0;
}