ZOJ3715Kindergarten Election(貪心+列舉)
阿新 • • 發佈:2018-12-24
題目大意:
n個小朋友選老大,給出除了一號小朋友外的所有人投票情況,已經1號小朋友需要賄賂i號小朋友來投他自己的花費。1號小朋友希望當老大,並且自己也需要投一票。問最小的花費。
分析:
列舉1號小朋友當選時的得票數。先把票數高於1號的小朋友用賄賂降下來,如果自己票數不夠,則選擇最小賄賂費的人賄賂。然後檢查一遍第二個人到最後一個人的票數是否小於等於當前列舉值-1,並且需要其中一個小朋友的票數小於當前列舉值-1,因為1號小朋友也需要投一票。
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; const int maxn = 105; struct Node { int cost, to; bool use; bool operator < (const Node &other)const { return cost < other.cost; } }nd[maxn]; int Get[maxn], vis[maxn], vot[maxn]; int main() { int T, n, tol; scanf("%d", &T); while(T--) { scanf("%d", &n); tol = 0; memset(Get, 0, sizeof(Get)); for(int i = 2; i <= n; i++) { scanf("%d", &vot[i]); Get[vot[i]]++; } for(int i = 2; i <= n; i++) { scanf("%d",&nd[tol].cost); if(vot[i] != 1) { nd[tol].to = vot[i]; nd[tol].use = false; tol++; } } sort(nd, nd+tol); int ans = 0x3f3f3f3f; for(int i = Get[1]; i <= n-1; i++) { int cost = 0; memcpy(vis, Get, sizeof(Get)); for(int j = 0; j < tol; j++) { if(vis[nd[j].to] >= i) { nd[j].use = true; cost += nd[j].cost; vis[nd[j].to]--; vis[1]++; } } for(int j = 0; j < tol && vis[1] < i; j++) { if(nd[j].use) continue; cost += nd[j].cost; nd[j].use = true; vis[nd[j].to]--; vis[1]++; } int j; for(j = 2; j <= n; j++) if(vis[j] < i-1) break; if(j <= n && vis[1] == i) ans = min(ans, cost); for(j = 0; j < tol; j++) nd[j].use = false; } cout << ans << endl; } return 0; }