LA4788
贪心
这个贪心不太懂啊 dfs返回子树需要的最小值,然后按需要减消耗排序,然后贪心选取即可。
#include<bits/stdc++.h> using namespace std; typedef pair<int, int> PII; const int N = 110; struct Node { int a, g, c; } node[N]; vector<int> G[N]; int cost[N], mx[N]; int n, ans, tot, kase; bool cp(int i, int j) { return cost[i] == cost[j] ? mx[i] > mx[j] : cost[i] < cost[j]; } bool cp1(int i, int j) { return mx[i] - cost[i] > mx[j] - cost[j]; } int dfs(int u, int last) { int ret = 0; vector<PII> vt; vt.clear(); for(int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if(v == last) continue; int need = dfs(v, u); cost[u] += cost[v]; vt.push_back(make_pair(need - cost[v], need)); } sort(vt.begin(), vt.end()); int pprev = 0; for(int i = vt.size() - 1; i >= 0; --i) { PII x = vt[i]; ret += max(x.second - pprev, 0); pprev = max(pprev, x.second); pprev -= x.second - x.first; } if(ret + node[u].g >= node[u].a) ret += node[u].g; else ret = node[u].a; cost[u] += node[u].g; return ret; } int main() { while(scanf("%d", &n)) { if(!n) break; for(int i = 1; i <= n; ++i) { scanf("%d%d%d", &node[i].a, &node[i].g, &node[i].c); node[i].g += node[i].c; } for(int i = 1; i <= n; ++i) G[i].clear(); for(int i = 1; i < n; ++i) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } ans = 1 << 29; for(int i = 1; i <= n; ++i) { memset(mx, 0, sizeof(mx)); memset(cost, 0, sizeof(cost)); ans = min(ans, dfs(i, 0)); } printf("Case %d: %d\n", ++kase, ans); } return 0; }