思路:
读完题意后,我们要求的是找一个联通的点集,使得点集的和为最大,权值在点上。
我们只需要求出每个点集的子树的总和即可。如果,某个的的儿子(子树的和为负数,那么我们就不计算这个儿子)。
代码:
#include <bits/stdc++.h> #define int long long //(有超时风险) #define PII pair<int,int> #define endl '\n' #define LL __int128 using namespace std; const int N=2e5+10,M=1e3+10,mod=998244353,INF=0x3f3f3f3f; int a[N]; int h[N],e[N],ne[N],idx; void add(int a,int b) { e[idx]=b;ne[idx]=h[a];h[a]=idx++; } int ans=0; int dfs(int x,int fa) { int tmp=a[x]; for(int i=h[x];i!=-1;i=ne[i]) { int j=e[i]; if(j==fa) continue; tmp+=max(0ll,dfs(j,x)); } ans=max(ans,tmp); return tmp; } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n;cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; memset(h,-1,sizeof h);idx=0; for(int i=1;i<n;i++) { int x,y;cin>>x>>y; add(x,y); add(y,x); } dfs(1,-1); cout<<ans<<endl; return 0; }
用vector
#include <bits/stdc++.h> #define int long long //(有超时风险) #define PII pair<int,int> #define endl '\n' #define LL __int128 using namespace std; const int N=2e6+10,M=1e3+10,mod=998244353,INF=0x3f3f3f3f; int a[N],b[N],c[N],pre[N]; signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n;cin>>n; vector<int>v(n+1); for(int i=1;i<=n;i++) cin>>v[i]; vector<vector<int>>g(n+10); int ans=0; function<int (int,int)> dfs=[&](int fa,int x) { int tmp=v[x]; for(auto t:g[x]) { if(t==fa)continue; tmp+=max(0ll,dfs(x,t)); } ans=max(ans,tmp); return tmp; }; for(int i=1;i<=n-1;i++) { int x,y;cin>>x>>y; g[x].push_back(y); g[y].push_back(x); } dfs(0,1); cout<<ans<<endl; return 0; }
P8625 [蓝桥杯 2015 省 B] 生命之树--2024蓝桥杯冲刺省一
最新推荐文章于 2024-03-31 12:30:50 发布