LCA-> Max Flow P(洛谷3128)

题意:n个节点m个询问,每次询问2个输入,u和v两个节点,代表u,v之间的路径权值+1。求m次询问后权值最大的节点。

分析:明显树上差分,将u,v作为区间起点,祖先作为和祖先的父亲作为差分区间结尾。
思考:为什么要从下往上差分,从上往下差分为什么不行呢

求LCA的时候算法写错了,往上跳的时候没跳u,把depth[u]跳了..


void solve(){
    int n, m;
    cin >> n >> m;

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

    int p = upper_bound(pow2_values.begin(), pow2_values.end(), n) - pow2_values.begin() - 1;
    vector<int> depth(n + 1);
    vector<vector<int>> dp(n + 1, vector<int>(p + 1));

    function<void(int, int, int)> dfs = [&](int u, int p, int d){
        depth[u] = d;
        dp[u][0] = p;
        for (int i = 1; (1 << i) <= d; ++i){
            dp[u][i] = dp[dp[u][i - 1]][i - 1];
        }
        for (const auto& v : al[u]){
            if (v != p){
                dfs(v, u, d + 1);
            }
        }
    };

    function<int(int, int)> lca = [&](int u, int v){
        if (depth[u] < depth[v]){
            swap(u, v);
        }
        for (int i = p; i >= 0; --i){
            if (depth[u] - (1 << i) >= depth[v]){
                u = dp[u][i];
            }
        }
        if (u == v){
            return u;
        }
        for (int i = p; i >= 0; --i){
            if (dp[u][i] != dp[v][i]){
                u = dp[u][i];
                v = dp[v][i];
            }
        }
        return (dp[u][0]);
    };

    dfs(1, 0, 1);
    vector<int> weight(n + 1);
    while (m --){
        int u, v;
        cin >> u >> v;
        int anc = lca(u, v);

        auto deal = [&](int ancestor){
            weight[ancestor] ++;
            for (auto& t : al[u]){
                if (t != dp[u][0]){
                    weight[t] --;
                }
            }
            for (auto& t : al[v]){
                if (t != dp[v][0]){
                    weight[t] --;
                }
            }
        };
        deal(anc);
    }

    int ans = 0;
    function<void(int, int, int w)> dfs_ = [&](int u, int p, int w){
        ans = max(ans, w);
        for (auto& v : al[u]){
            if (v != p){
                dfs_(v, u, w + weight[v]);
            }
        }
    };

    dfs_(1, 0, weight[1]);

    cout << ans << '\n';
}
posted @ 2024-01-14 10:35  _Yxc  阅读(15)  评论(0)    收藏  举报