[CF1029E] Tree with Small Distances - 贪心,树形dp

Description

给定一颗有根树(根节点为 \(1\))。要求往树中加入一些边使得从根节点到其他节点的距离至多是 \(2\)。 求加入边的最小数量。

Solution

贪心,每次将叶子的父亲向根连边,不断重复即可

暴力做挺麻烦,考虑对点染色(然后变成了一个类似树形 dp 的东西)

叶子染色为 2,其余点为所有孩子的最小值 +1 后对 3 取模

这样染出来,0 表示这个点有往根的连边,1 表示这个点的某个孩子有往根的连边,2 表示这个点的父亲有往根的连边

根和根的孩子是不需要考虑的,统计答案的时候忽略掉即可

#include <bits/stdc++.h>
using namespace std;

#define int long long

const int N = 1e6 + 5;

int n, f[N], fa[N];
vector<int> g[N];

void dfs(int p, int from = 0)
{
    f[p] = 2;
    for (int q : g[p])
    {
        if (q == from)
            continue;
        fa[q] = p;
        dfs(q, p);
        f[p] = min(f[p], (f[q] + 1) % 3);
    }
}

signed main()
{
    ios::sync_with_stdio(false);

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

    dfs(1);

    int ans = 0;
    for (int i = 2; i <= n; i++)
        if (f[i] == 0 && fa[i] != 1)
            ++ans;
    cout << ans << endl;
}

相关文章: