树上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就慢了。
---- suffer now and live the rest of your life as a champion ----