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
", ++kase, ans);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/19992147orz/p/7148903.html