ZOJ 3715 Kindergarten Election【枚举】

版权声明:学习,哪有那么多条条框框~ https://blog.csdn.net/Irish_Moonshine/article/details/89358250

ZOJ 3715 Kindergarten Election
题意:班级班长选举投票(每个人都不能投自己且一人一票),票数总值大于其他所有人的同学当选。现在有一个小朋友想成为班长,每个同学可以用x个糖果收买使其转投自己。

分析:直接猜想策略难以把握,并且无法验证正确性。所以不妨枚举这个小朋友最后以多少票当选班长,那么其他同学就肯定低于这个票数。即
R e s = C n t 使 n 1 + C n t , Res=Cnt_{使得所有同学的票数低于n-1的花费}+Cnt_{所有同学满足条件后,补全这个小朋友差的票数}
A n s = m i n ( A n s , R e s ) Ans=min(Ans,Res)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define ll long long int
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e3 + 10;
void init();
int cost[maxn]; int tcos[maxn];
struct node {
	int id, val;
};
node vain[123][maxn];
int cmp(node a, node b) {
	return a.val < b.val;
}
int van[123];
int len[maxn];
int n;

int main() {
	int T;
	scanf("%d", &T);
	while (T--) {
		scanf("%d", &n);
		init();
		for (int i = 2; i <= n; i++) {
			scanf("%d", &van[i]); 
		}
		for (int i = 2; i <= n; i++) {
			scanf("%d", &cost[i]);
		}
		for (int i = 2; i <= n; i++) {
			len[van[i]]++;
			vain[van[i]][len[van[i]]].id = i;
			vain[van[i]][len[van[i]]].val = cost[i];
		}
		for (int i = 1; i <= n; i++) {
			if (len[i]) {
				sort(vain[i] + 1, vain[i] + 1 + len[i], cmp);
			}
		}
		int Min = INF;
		for (int k = 2; k <= n; k++) {
			int ans = 0;
			int tmp = len[1];
			int top = k-1;
			for (int i = 2; i <= n; i++) tcos[i] = cost[i];
			for (int i = 2; i <= n; i++) {
				if (len[i] > top) {
					for (int j = 1; j <= len[i] - top; j++) {
						ans += vain[i][j].val; tmp++;
						tcos[vain[i][j].id] = INF;
					}
				}
			}
			sort(tcos + 2, tcos + 1 + n);
		
			for (int i = 2; i <= top + 1 - tmp + 1; i++) {
				ans += tcos[i];
			}
			Min = min(ans, Min);
		}
		cout << Min << endl;
	}
	return 0;
}
void init() {
	for (int i = 0; i <= n; i++) {
		cost[i] = 0; van[i] = 0; len[i] = 0;
	}
}

猜你喜欢

转载自blog.csdn.net/Irish_Moonshine/article/details/89358250
ZOJ