F:Maximum White Subtree(樹形dp)

Maximum White Subtree

思路

如果考慮其覆蓋範圍只會到其子樹上,不會到其父節點上的話(假設的情況),這道題就非常好寫了,就是一個簡單的自底向上傳遞的樹形dpdp。所以我們還要考慮的就是連接其父節點,因此我們只需要再進行一個自頂下向傳遞的樹形dpdp即可。

第一遍的dfsdfs比較簡單,但是第二遍的dfsdfs有一些細節需要考慮,我在下面的代碼中給出了註釋。

寫完後找了題解,好像這是換根dp?dp?,蒟蒻我沒有學過啥換根dpdp

代碼

#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back

using namespace std;

typedef pair<int, int> pii;
typedef long long ll;
typedef unsigned long long ull;

const double eps = 1e-7;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    } 
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

const int N = 2e5 + 10;

int head[N], nex[N << 1], to[N << 1], cnt = 1;
int dp[N], a[N], n;

void add(int x, int y) {
    to[cnt] = y;
    nex[cnt] = head[x];
    head[x] = cnt++;
}

void dfs1(int rt, int fa) {
    if(a[rt] == 0)  dp[rt] = -1;//設置dp數組的初值,這個應該比較簡單理解。
    else dp[rt] = 1;
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa) continue;
        dfs1(to[i], rt);
        dp[rt] = max(dp[rt], dp[rt] + dp[to[i]]);//兩種選擇,與其子樹連接或者不連接。
    }
}

void dfs2(int rt, int fa) {
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa) continue;
        dp[to[i]] = max(dp[to[i]], dp[to[i]] + dp[rt] - max(dp[to[i]], 0));
        //這個的de[rt] - max(dp[to[i]], 0),表示的意思是:如果這個節點在上一躺的dfs中選擇了這個兒子節點那麼這個點一定是正數,如果這個點是負數,那麼他在上一躺就沒有被選擇到,所以我們不需要減去這個點的值。
        dfs2(to[i], rt);
    }
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    n = read();
    for(int i = 1; i <= n; i++) a[i] = read();
    for(int i = 1; i < n; i++) {
        int x = read(), y = read();
        add(x, y);
        add(y, x);
    }
    dfs1(1, -1);
    dfs2(1, -1);
    for(int i = 1; i <= n; i++)
        printf("%d%c", dp[i], i == n ? '\n' : ' ');
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章