题解 P1122 【最大子树和】
linyinuo2008 · · 题解
原题链接
树形
1、题意理解
给你一棵有
数据范围:
2、算法分析
从这里借两张图。
看样例,我们不难发现所说的“最大子树和”就在这里:
所以我们该怎样设计状态呢,很简单!就是树形
然后我们遍历
这样以
结果:
我们可以用vector来建树(常数这么小的东西咱们不用?),最后附上个树形
void dfs(int u,int fa)
{
Init();
vis[u]=1;//有时要(可以)加,本题不用加
for(int i=0;i<tree[u].size();i++)
{
int nxt=tree[u][i];
if(nxt!=fa&&!vis[nxt])
{
dfs(nxt,u);
dp();
}
}
}
3、代码
代码中有注释。
#include <iostream>
#include <vector>
using namespace std;
const int N=16005;
int a[N],n,f[N];//f[i]表示以i为根节点最大子树和
vector<vector<int> > tree(N);//vector建树
void dfs(int u,int fa)//当前节点与其父亲节点
{
f[u]=a[u];//初始化为节点点权
for(int i=0;i<tree[u].size();i++)//遍历每个节点
{
if(tree[u][i]!=fa)//不能往回搜父亲
{
int nxt=tree[u][i];
dfs(nxt,u);
if(f[nxt]>0)
f[u]+=f[nxt];//动归转移
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n-1;i++)
{
int p,q;
cin>>p>>q;
tree[p].push_back(q);//无向边要push两次
tree[q].push_back(p);
}
dfs(1,0);//这里其实从任何一个节点开始搜都可以,因为是一次性的
int ans=-0x7f7f7f;
for(int i=1;i<=n;i++)
ans=max(ans,f[i]);//求结果
cout<<ans;
return 0;
}
若有错误,欢迎指出!