题目描述

byteland的王后深受百姓爱戴。为了表达他们的爱,国民们打算占领一个新的国家,并以王后的名字命名。这个国家有n座城市。城市之间有双向道路连接,且每两个城市之间有且仅有一条道路。每座城市对其拥有者来说都有一定的收益。尽管国民们非常爱戴他们的王后,他们并不一定会征服所有的城市献给她。他们只想占领一部分城市(至少有一座),这些城市必须满足两个条件:所有被占领的城市相互间必须是连通的,且城市收益之和最大。你的任务就是算出最大收益是多少。

输入输出格式

输入格式:

第一行是城市的数量n(1<=n<=16000)。第二行包含n个整数,依次表示每座城市的收益,每个数是-1000到1000之间的整数。下面的n-1行描述了道路:每行包含2个整数a和b,用一个空格隔开,表示这两个城市之间有一条道路。

输出格式:

仅有一个数,表示最大收益。

输入输出样例

输入样例#1:

5
-1 1 3 1 -1
4 1
1 3
1 2
4 5
输出样例#1:

4

水树规。

没有点数限制,所以直接枚举每个子树选或不选。

 /*by SilverN*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n;
int w[mxn];
struct edge{
int v,nxt;
}e[mxn<<];
int hd[mxn],mct=;
void add_edge(int u,int v){
e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;
return;
}
int f[mxn];
int ans=;
void DP(int u,int fa){
for(int i=hd[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==fa)continue;
DP(v,u);
f[u]=max(f[u],f[u]+f[v]);
}
ans=max(ans,f[u]);
return;
}
int main(){
n=read();
int i,j,u,v;
for(i=;i<=n;i++)w[i]=read(),f[i]=w[i];
for(i=;i<n;i++){
u=read();v=read();
add_edge(u,v);
add_edge(v,u);
}
DP(,);
printf("%d\n",ans);
return ;
}
05-11 16:54