题意:给你一棵带有点权的树,让你求最大的两个不想交的子树的点权和
题解:
树形dp,dp[u]记录u的子树中权值最大的子树的sum值(包括它本身)
具体的状态转移方程很好理解
最主要就是没做过类似题目,可能比较难以想到
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define PB push_back
#define MP make_pair
#define ll long long
#define MS(a,b) memset(a,b,sizeof(a))
#define LL (rt<<1)
#define RR (rt<<1|1)
#define lson l,mid,LL
#define rson mid+1,r,RR
#define pii pair<int,int>
#define pll pair<ll,ll>
#define lb(x) (x&(-x))
void In(){freopen("in.in","r",stdin);}
void Out(){freopen("out.out","w",stdout);}
const int N=2e5+10;
const int M=3e5+10;
const int Mbit=1e6+10;
const ll inf=1e15;
const ll mod=1e9+7;
ll val[N],dp[N],ans;
vector<int>G[N];
void dfs(int u,int fa)
{
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(v==fa)continue;
dfs(v,u);
val[u]+=val[v];
if(dp[u]!=-inf)ans=max(ans,dp[u]+dp[v]);
dp[u]=max(dp[u],dp[v]);
}
dp[u]=max(dp[u],val[u]);
}
int main()
{//In();
int n;
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++)scanf("%lld",&val[i]);
for(int i=1;i<=n;i++)G[i].clear(),dp[i]=-inf;
ans=-inf;
for(int i=1;i<n;i++){
int u,v;scanf("%d%d",&u,&v);
G[u].PB(v);G[v].PB(u);
}
dfs(1,-1);
if(ans!=-inf)printf("%lld\n",ans);
else puts("Impossible");
}
return 0;
}