CF1187E Tree Painting 题解

闲话:
第一道自己完全独立做出的换根 dp,根绝本题还是比较经典的。
难度:2100


跟其他换根 dp 的题目一样,第一步你需要先求出以任何一个节点为根的答案。

然后以 O ( n ) O(n) O(n) 的时间复杂度将以其他为根的答案(也就是再做一遍搜索)。

首先,我把 1 1 1 号节点作为根来算第一步的答案,这个就是普通的树形 ,非常 easy,这里就不再赘述了。

通过观察题目中给的图可以发现,如果已经知道某个点的父亲那么就可以根据如下的公式算出以这个点为根的答案:
d p u = d p f a t h e r − s i z u + ( n − s i z u ) dp_u = dp_{father} - siz_u + (n - siz_u) dpu=dpfathersizu+(nsizu)

思路清晰以后写代码就是不费吹灰之力的事情了,简直是易如反掌。

#include 
using namespace std;

const int N = 2e5 + 10;
vector<int> G[N];
typedef long long ll;
ll siz[N], f[N];
int n;

void dfs1(int u, int fa) {
    siz[u] = 1;
    for (auto v : G[u]) {
        if (v != fa) {
            dfs1(v, u);
            siz[u] += siz[v];
        }
    }
    f[1] += siz[u];
}

void dfs2(int u, int fa) {
    for (auto v : G[u]) {
        if (v != fa) {
            f[v] = f[u] - siz[v] + (n - siz[v]);
            dfs2(v, u);
        }
    }
}

int main() {
    cin >> n;
    for (int i = 1; i <= n - 1; i++) {
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs1(1, -1);
    dfs2(1, -1);
    ll res = 0;
    for (int i = 1; i <= n; i++) {
        res = max(res, f[i]);
    }
    cout << res << "\n";
    return 0;
}

你可能感兴趣的:(算法,深度优先,动态规划)