Educational Codeforces Round 136 (Rated for Div. 2) D. Reset K Edges

这道题目我们可以考虑二分做,二分出最终的深度,然后尝试是否能使用不超过\(k\)次操作使得深度符合条件。

考虑如何和判断,我们可以从根节点开始搜索,如果当前点的深度为\(mid + 1\),就对当前点进行操作。但很可惜,这种贪心方法可以很容易的举出反例,比如深度为\(mid\)的点下面有很多个叶子,此时不应该是修改叶子,而是修改深度为\(mid\)的点更优。

考虑反过来贪心,如果我们从叶子开始搜索,如果当前的点的深度为\(mid - 1\)且父节点不是根,则把当前点插到根上。

注意到题目保证了\(p_i < i\),所以我们直接倒序枚举就好了。

#include<bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

const int mod = 1e9 + 7;

void solve() {
    int n, k;
    cin >> n >> k;
    vector<int> p(n + 1);
    for (int i = 2; i <= n; i++)
        cin >> p[i];
    int l = 1, r = n - 1, res = -1;
    while (l <= r) {
        int mid = (l + r) / 2, cnt = 0;
        vector<int> dis(n + 1);
        for (int i = n; i > 1; i--) {
            if (dis[i] == mid - 1 and p[i] != 1) cnt++;
            else dis[p[i]] = max(dis[p[i]], dis[i] + 1);
        }
        if (cnt <= k) res = mid, r = mid - 1;
        else l = mid + 1;
    }
    cout << res << "\n";
}

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int T;
    cin >> T;
    while (T--)
        solve();
    return 0;
}
posted @ 2024-09-20 15:07  PHarr  阅读(8)  评论(0编辑  收藏  举报