Codeforces Round 975 (Div. 1) C Solution

闲话

因为累所以没打,感觉有点亏。

题解

该解法与官方解法不同

对于一个固定的深度,为了仅保留对应深度的叶子,显然需要进行以下两种操作:

  1. 删除所有深度大于指定深度的节点
  2. 删除所有深度小于指定深度的叶子

对于任意一个深度为 \(d\) 的叶子,将其删除后有两种可能:

  1. 若其父节点只有一个儿子,即该节点,则删除后会新增一个深度为 \((d-1)\) 的叶子。
  2. 若其父节点不止一个儿子,则删除后不会产生新的叶子。

对于上方提到的操作,操作 \(2\) 的操作次数可以简单地使用后缀和计算。考虑如何计算操作 \(1\) 所用的操作次数。

答案是,我们可以直接暴力删除。

我们按升序枚举所有可能的最终固定深度,对于上一次枚举的最终固定深度上的所有叶子节点,我们显然需要不断地删去它们直到出现上述提到的两种可能中的第 \(2\) 种,即不产生新的叶子。这一点可以简单地通过存储每一个节点的度数和父节点实现。

由于每个节点最多会被删去一次,那么设节点的最大深度为 \(D\),则总时间复杂度为 \(O(n+D)\)

代码

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N = 5e5 + 10;
int n, idx, deg[N], f[N], dep[N], dpc[N], res, prc;
vector<int> road[N], dpv[N];
void dfs(int x)
{
    idx = max(idx, dep[x]);
    dpc[dep[x]]++;
    if (road[x].size() == 1)
    {
        dpv[dep[x]].emplace_back(x);
        return;
    }
    for (auto &i : road[x])
    {
        if (i == f[x])
            continue;
        f[i] = x;
        dep[i] = dep[x] + 1;
        dfs(i);
    }
}
void prune(int x)
{
    do
    {
        x = f[x];
        deg[x]--;
        prc++;
    } while (deg[x] == 1);
}
void run()
{
    scanf("%d", &n);
    memset(deg + 1, 0, n << 2);
    memset(dpc + 1, 0, idx << 2);
    for (int i = 1; i <= n; i++)
    {
        road[i].clear();
    }
    for (int i = 1; i <= idx; i++)
    {
        dpv[i].clear();
    }
    idx = 0;
    for (int i = 1, x, y; i < n; i++)
    {
        scanf("%d%d", &x, &y);
        deg[x]++, deg[y]++;
        road[x].emplace_back(y);
        road[y].emplace_back(x);
    }
    deg[1] = 0;
    for (auto &i : road[1])
    {
        dep[i] = 1;
        f[i] = 1;
        dfs(i);
    }
    for (int i = idx - 1; i; i--)
    {
        dpc[i] += dpc[i + 1];
    }
    dpc[idx + 1] = 0;
    res = n - 1;
    prc = 0;
    for (int i = 1; i <= idx; i++)
    {
        for (auto &j : dpv[i - 1])
        {
            prune(j);
        }
        res = min(res, prc + dpc[i + 1]);
    }
    printf("%d\n", res);
}
int main()
{
    int T = 1;
    scanf("%d", &T);
    while (T--)
        run();
}
posted @ 2024-09-28 09:58  丝羽绫华  阅读(149)  评论(0编辑  收藏  举报