题目链接:http://cojs.tk/cogs/problem/problem.php?pid=967
分析:
树结构,首先任取一个节点,用深搜构造一棵树。
由于蒟蒻不会邻接表,只有用vector了,还开了两个。。
然后深搜处理处理这棵树。
对于每个父节点,它的每个子节点都有取或不取两种情况,如果子节点能取到的最大的值大于零,那么就取,否则舍弃。而对于这个父节点,如果它能取到的最大值大于零,那么将这个值向上传递,否则返回0,代表不取。
另外由于最优解可能取不到根节点,所以要在过程中不断记录更新最大值,最后输出最大值,而不一定是根节点的值。
代码:
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
vector<int> g[200001],g1[200001];
bool b[200001]={false};
int a[200001],n,mx=-1000000;
void make_tree(int i) //递归建树
{
int hi=g[i].size();
for (int j=0;j<hi;j++)
{
if (b[g[i][j]]!=true) //如果已经在树中,舍去
{
b[g[i][j]]=true;
g1[i].push_back(g[i][j]);
make_tree(g[i][j]);
}
}
}
int work(int i) //递归求解
{
int hi=g1[i].size();
if (hi==0)
{
mx=max(mx,a[i]); // 不断更新最大值
return max(a[i],0);
}
int ans=a[i];
for (int j=0;j<hi;j++)
{
ans+=work(g1[i][j]);
mx=max(mx,ans);
}
return max(ans,0);
}
int main()
{
freopen("photo.in","r",stdin);
freopen("photo.out","w",stdout);
cin>>n;
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<n;i++)
{
int aa,bb;
scanf("%d%d",&aa,&bb);
g[aa].push_back(bb);
g[bb].push_back(aa);
}
b[1]=true;
make_tree(1);
cout<<max(work(1),mx);
return 0;
}