A. Copil Copac Draws Trees

https://codeforces.com/contest/1830/problem/A

题意:给定一棵树,初始时只有节点1。再给定n - 1条边,不断的扫描n - 1条边,如果边{u, v}已经在树中,则将边加入到树中,问建完树需要扫描多少次边?

思路:动态规划,从节点1做dfs。然后考虑当前的边{u, v}。假如{u, v}在输入序列中出现的顺序,比{p, u}靠后,那么dp[v] = inputIndex[{u, v}]; 否则,此时{p, u}的扫描次数已经计算出来,{u, v}的inputIndex在{p, u}的activeInex前面,那么dp[u] = dp[v] + 1,这种逻辑保证在考虑节点v前,dp[u]的数值总是有效的,最后去dp里取最大值即可。

总结:没有更好的理解题解,主要是那些变量太傻逼了,一会index[], 一会id[],不如改成inputIndex和activeIndex更好理解一点。

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

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

    auto dfs = [&](auto&& self, int u, int p) ->void{
        for (const auto& v : al[u]) {
            if (v == p) {
                continue;
            }
            dp[v] = dp[u] + (index[{u, v}] < activeIndex[u]);
            activeIndex[v] = index[{u, v}];
            self(self, v, u);
        }
    };

    dp[1] = 1;
    dfs(dfs, 1, 0);
    cout << *max_element(dp.begin() + 1, dp.end()) << '\n';
}
posted @ 2025-06-17 09:31  _Yxc  阅读(4)  评论(0)    收藏  举报