← 返回题目页

A1812 [GESP-7.2412.T2] 燃烧

标程

#include <bits/stdc++.h>
using namespace std;

// [GESP-7.2412.T2] 燃烧
//
// 从 u 引燃后,火只能向「权值严格小于自己」的相邻节点扩散,
// 所以烧到的节点就是从 u 出发、权值沿路严格递减的那些节点。
//
// 记 f[u] = 从 u 引燃能烧掉的节点数(含 u 自己),则
//     f[u] = 1 + sum{ f[v] : v 与 u 相邻且 a[v] < a[u] }
// 因为图是一棵树,不同邻居的「下方区域」互不相交,不会重复计算。
//
// 计算顺序:按权值从小到大处理,算 f[u] 时所有权值更小的邻居都已经算好了。
// 最后取所有 f[u] 的最大值。

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;

    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++) cin >> a[i];

    vector<vector<int>> g(n + 1);
    for (int i = 0; i < n - 1; i++) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    // 按权值从小到大排序,保证算 f[u] 时权值更小的邻居都算好了
    vector<int> ord(n);
    iota(ord.begin(), ord.end(), 1);
    sort(ord.begin(), ord.end(), [&](int x, int y) { return a[x] < a[y]; });

    vector<int> f(n + 1, 0);
    int ans = 0;
    for (int u : ord) {
        f[u] = 1;  // 自己
        for (int v : g[u]) {
            if (a[v] < a[u]) f[u] += f[v];
        }
        ans = max(ans, f[u]);
    }

    cout << ans << "\n";
    return 0;
}

动画演示