传送门:http://codeforces.com/contest/743/problem/D
题意:有n个点,编号为1~n,n个点构成以1为根节点的树,每个节点都有相应的权值,要求找出2个不相交的子树使得权值和最大
题解:树型dp,对于每个点u,找出其权值最大的子树和权值次大的子树,如果两者都存在则将两者之和与ans比较,ans取较大值
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int MX = 2e5 + 5;
struct Edge{
int v,nxt;
}edge[MX*2];
int head[MX],tot;
void add(int u,int v){
edge[tot].v=v;
edge[tot].nxt=head[u];
head[u]=tot++;
}
typedef long long LL;
LL val[MX],Max[MX],Max2[MX],ans;
const LL inf = 0x3f3f3f3f3f3f3f3f;
LL dfs(int u,int fa){
Max[u]=Max2[u]=-inf;
LL cnt;
for(int i=head[u];~i;i=edge[i].nxt){
int v=edge[i].v;
if(v==fa) continue;
cnt=dfs(v,u);
val[u]+=val[v];
if(cnt>Max[u]) {Max2[u]=Max[u];Max[u]=cnt;}
else if(cnt>Max2[u]) Max2[u]=cnt;
if(Max2[u]>-inf) ans=max(ans,Max[u]+Max2[u]);
}
return max(val[u],Max[u]);
}
int main(){
int n;
// freopen("in.txt","r",stdin);
while(~scanf("%d",&n)){
memset(head,-1,sizeof(head));
tot=0;
for(int i=1;i<=n;i++) scanf("%I64d",&val[i]);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
ans=-inf;
dfs(1,0);
if(ans>-inf) printf("%I64d\n",ans);
else printf("Impossible\n");
}
return 0;
}