树上DP - 最大权连通子树 - 洛谷P1122 - 最大子树和

 

这道题想了好久。看到这篇题解后瞬间懂了。关键理解这句话:选择哪个点为根对结果没有影响,毕竟任意连通分量在任意时刻总是可以看成一颗以某个点为根的数

一想通后,这个题就和普通的树上dp没有任何区别了。

代码:

#include <iostream>
#include <vector>
#define MAX(a,b) (a>b?a:b)
#define Maxsize 16000+1
using namespace std;
bool vis[Maxsize];
int dp[Maxsize];
vector<int> vec[Maxsize];
void dfs(int root){
    for (auto it = vec[root].begin(); it != vec[root].end(); it++) {
        if(!vis[*it]){
            vis[*it] = true;
            dfs(*it);
            vis[*it] = false;
        }
    }
    
    for (auto it = vec[root].begin(); it != vec[root].end(); it++) {
        if(!vis[*it]){
            dp[root] += MAX(dp[*it],0);
        }
    }
}
int main(){
    int n;
    int a,b;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> dp[i];
    }
    for (int i = 1; i < n; i++) {
        cin >> a >> b;
        vec[a].push_back(b);
        vec[b].push_back(a);
    }
    vis[1] = true; // 注意初始化根为true
    dfs(1); 
    int ans = -0x3fffffff;
    for (int i = 1; i <= n; i++) {
        ans = MAX(ans,dp[i]);
    }
    cout << ans;
    return 0;
}

 另外这题还可以用换根dp来做,不过没必要。因为换根dp是解决每一点的最大权连通子树,而这一题只需要求出一颗子树即可。(慢慢体会吧,也许我表达的不清楚?)

 总之这题换根dp就慢了。

posted @ 2020-03-17 13:18  popozyl  阅读(371)  评论(0编辑  收藏  举报