A. Parsa's Humongous Tree

https://codeforces.com/problemset/problem/1528/A

题意:给一个树,树中每个节点有一个取值范围。现要对每个点在取值范围内选一个数值,然后求每条边的权值和最大是多少,边的权值是相邻的点取值后相减的绝对值。

思路:动态规划,每个节点维护两种状态:当前节点取最大值和取最小值,以当前节点为根的子树的最大权重。考虑当前根节点为u的树,不断从子树中选取两种情况的最优解来更新两种状态即可。

总结:为什么一定是两个端点的数值?假如考虑当前的节点u,如果相邻节点比u大的多,那u越小,答案更优,反之亦然。所以取值时,一定是取两个端点中的其中一个。

inline void solve() {
    int n;
    cin >> n;

    vector<pair<int, int>> a(n);
    for (auto& [x, y] : a) { 
        cin >> x >> y;
    }

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

    vector<array<long long, 2>> dp(n, {0ll, 0ll});
    auto dfs = [&](auto&& self, int u, int p) ->void {
        for (const auto& v : al[u]) {
            if (v == p) {
                continue;
            }
            self(self, v, u);
            dp[u][0] += max(dp[v][0] +abs(a[v].first - a[u].first), 
                dp[v][1] + abs(a[v].second - a[u].first));
            dp[u][1] += max(dp[v][0] + abs(a[v].first -a[u].second), 
                dp[v][1] +abs(a[v].second - a[u].second));
        }
    };

    dfs(dfs, 0, -1);
    
    cout << max(dp[0][0], dp[0][1]) << '\n';
}
posted @ 2025-05-31 08:52  _Yxc  阅读(10)  评论(0)    收藏  举报