P1122 最大子樹和 題解
阿新 • • 發佈:2020-09-16
簡要題意:
給定一棵 \(n\) 個節點的樹,有點權,求其中最大的連通塊之和。
資料範圍:\(n \leq 1.6 \times 10^4\).
很顯然,考慮用樹形 \(\text{dp}\) 解決此題。
\(f_u\) 表示以 \(u\) 為根的子樹中 包含 \(u\) 節點 的答案。
則易得:
\[f_u = a_u + \max_{v \in \text{subtree}(u)} \max(f_v , 0) \]
時間複雜度:\(\mathcal{O}(n)\).
實際得分:\(100pts\).
#pragma GCC optimize(2) #include<bits/stdc++.h> using namespace std; const int N=1.6e4+1; inline int read(){char ch=getchar(); int f=1; while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();} int x=0; while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f;} inline void write(int x) { if(x<0) {putchar('-');write(-x);return;} if(x<10) {putchar(char(x%10+'0'));return;} write(x/10);putchar(char(x%10+'0')); } int n,a[N],f[N]; vector<int> G[N]; int ans=-(1<<31); inline void dfs(int u,int fa) { f[u]=a[u]; for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(v==fa) continue; dfs(v,u); f[u]+=max(f[v],0); } } int main() { n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<n;i++) { int u=read(),v=read(); G[u].push_back(v); G[v].push_back(u); } dfs(1,0); for(int i=1;i<=n;i++) ans=max(ans,f[i]); printf("%d\n",ans); return 0; }