zoukankan      html  css  js  c++  java
  • 【每日一题】11.黑白树 (树上DFS)

    补题链接:Here

    题目描述

    一棵 (n) 个点的有根树,(1) 号点为根,相邻的两个节点之间的距离为 (1) 。树上每个节点 (i)对应一个值(k[i])。每个点都有一个颜色,初始的时候所有点都是白色的。
    你需要通过一系列操作使得最终每个点变成黑色。每次操作需要选择一个节点 (i)(i) 必须是白色的,然后 (i) 到根的链上(包括节点 (i) 与根)所有与节点 (i) 距离小于 (k[i]) 的点都会变黑,已经是黑的点保持为黑。问最少使用几次操作能把整棵树变黑。

    输入描述:

    第一行一个整数 (n) ((1 ≤ n ≤ 10^5) )

    接下来 (n-1) 行,每行一个整数,依次为 (2) 号点到 (n) 号点父亲的编号。 最后一行 (n) 个整数为 (k[i] (1 ≤ k[i] ≤ 10^5))

    样例解释:

    对节点 (3) 操作,导致节点 (2) 与节点 (3) 变黑

    对节点 (4) 操作,导致节点(4) 变黑

    对节点 (1) 操作,导致节点 (1) 变黑

    输出描述:

    一个数表示最少操作次数

    示例1

    输入

    4
    1
    2
    1
    1 2 2 1
    

    输出

    3
    

    Solution

    由题意可知叶子节点必定要染色。对于其他节点:

    • 若此节点的已经染色的子节点中,可以将它覆盖,那么不需要染色,并借助这个点能覆盖的范围更新最大范围。
    • 若此节点的已经染色的子节点中,不能将它覆盖,那么需要将其子节点中范围最大的点染色,并更新最大范围。

    可以发现这是一个由子节点向父节点更新的过程,所以可以使用 (DFS) 。每次贪心地更新能覆盖的最大距离,不能覆盖就进行染色。

    • 时间复杂度:(mathcal{O}(n))

    const int N = 1e5 + 10;
    vector<int>e[N], k(N, 0), f(N, 0);
    int ans = 0;
    void dfs(int u, int fa) {
        for (int i = 0; i < e[u].size(); ++i) {
            int v = e[u][i];
            dfs(v, u);
            f[u] = max(f[u], f[v] - 1); //维护f值——儿子的f值-1之后的最大值
            k[u] = max(k[u], k[v] - 1); //维护k值——儿子的k值-1和自己的k值的最大值
        }
        // cout << f[u] << " " << k[u] << "
    ";
        //下面的点都覆盖不到它了——选他自己,此时就要更新 f 值
        if (f[u] == 0) ++ans, f[u] = k[u];
    }
    void solve() {
        int n;
        cin >> n;
        for (int i = 2, x; i <= n; ++i) {
            cin >> x;
            e[x].push_back(i);
        }
        for (int i = 1; i <= n; ++i) cin >> k[i];
        dfs(1, 0);
        cout << ans;
    }
    

    如果深度理解这道题以后可以直接在solve里写DFS,此时运行速度会快很多 (60ms -> 18ms)

    const int N = 1e5 + 10;
    void solve() {
        int n;
        vector<int> p(N), k(N), f(N), g(N, 0);
        cin >> n;
        for (int i = 2; i <= n; ++i) cin >> p[i];
        for (int i = 1; i <= n; ++i) cin >> k[i];
        int ans = 0;
        for (int i = n; i; --i) {
            g[i] = max(g[i], k[i]);
            if (f[i] == 0) ++ans, f[i] = g[i], g[i] = 0;
            f[p[i]] = max(f[p[i]], f[i] - 1);
            g[p[i]] = max(g[p[i]], g[i] - 1);
        }
        cout << ans << "
    ";
    }
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    ZOJ 2158 Truck History
    Knight Moves (zoj 1091 poj2243)BFS
    poj 1270 Following Orders
    poj 2935 Basic Wall Maze (BFS)
    Holedox Moving (zoj 1361 poj 1324)bfs
    ZOJ 1083 Frame Stacking
    zoj 2193 Window Pains
    hdu1412{A} + {B}
    hdu2031进制转换
    openjudge最长单词
  • 原文地址:https://www.cnblogs.com/RioTian/p/14678346.html
Copyright © 2011-2022 走看看