题面:
![](https://img-blog.csdnimg.cn/img_convert/d2d03b575f772cabd802970048c3683f.png)
解题:
树形数据结构
不妨用一个类 Tree 来储存每个节点的数据,其中除了它上面和下面与之相连接的节点,我还引入了两个变量:m_Num和f,分别用于储存其节点的自身值、从上往下加到该枝头的最大子树和……
DFS(深度优先搜索)
引用高赞题解区大佬神云_cloud的图来解释说明:
下图中,1/2/3号节点均只连接一端,则可以将其视为“叶子”或“顶端”,
定义严格的搜索顺序是从上往下,则其f值(最大子树和)就是它本身,f[1]=f[2]=f[3]=-1;
对于1/2/3号节点下方的4/5/6号节点,其f值除了加上自身外,还要考虑要不要加上其上方节点的值,
f[4]=max(m_Num[4]+f[1])=1,f[1]是负数所以把1-4的枝条剪断,同理可求f[5]=f[6]=1;
![](https://img-blog.csdnimg.cn/img_convert/56ed483252a1a8379f659860fe089f05.png)
对于7号节点,我们可将其视为树根,递归将在这里结束,观察到其上方有4/5/6三个节点,
连接4/5/6号节点都要判断是否剪断,因此,创建临时变量tempSum:
int tempSum=0;
tempSum=max(tempSum , tempSum+f[4]);//判断4-7是否要剪断,若不剪断,tempSum+f[4]
tempSum=max(tempSum , tempSum+f[5]);//判断5-7是否要剪断,若不剪断,tempSum+f[5]
tempSum=max(tempSum , tempSum+f[6]);//判断6-7是否要剪断,若不剪断,tempSum+f[6]
f[7]=max(f[7],m_Num[7]+tempSum);
构建数据过程结束,接下来只要简单地遍历所有节点,找出最大的f值即答案
AC代码奉上
#include<iostream>
#include<algorithm>
#include<vector>
#define MAXN int(2e6+5)
using namespace std;
class Tree //树形数据结构,用类来管理
{
public:
vector<int>a_T; //aboveTree 上端树
vector<int>b_T; //behindTree 下端树
int m_Num = 0; //节点自身值
int f = 0; //加到该枝时的最大和
Tree(int num)
{
this->m_Num = num; //构造函数初始化节点自身值
this->f = num; //加到自身时,必须要算上自己的节点值
this->a_T.push_back(0);//占掉0位,从1开始
this->b_T.push_back(0);//占掉0位,从1开始
}
};
int n, root, a[MAXN] = { 0 };
vector<Tree>v;//存放树节点的容器
void dfs(int id, int pre) //从一个顶端,搜索到底端 注:pre参数只判断是不是顶端,没用……
{
if (pre != 0)
{
int tempSum = 0;
for (int i = 1; i <= v[id].a_T.size() - 1; i++)
{
tempSum = max(tempSum, tempSum + v[v[id].a_T[i]].f);
}
v[id].f = max(v[id].m_Num + tempSum, v[id].f);
}
for (int i = 1; i <= v[id].b_T.size() - 1; i++)
dfs(v[id].b_T[i], id);
if (v[id].b_T.size() == 1) { root = id; return; }
}
int main()
{
v.push_back(Tree(0));
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
Tree t(a[i]);
v.push_back(t); //初始化n个树节点
}
for (int i = 1; i <= n - 1; i++)
{
int p, q; //需要连接的枝条两端
cin >> p >> q;
v[p].b_T.push_back(q); //连接,p、q谁上谁下无所谓
v[q].a_T.push_back(p);
}
for (int i = 1; i <= v.size() - 1; i++)
if (v[i].a_T.size() == 1)dfs(i, 0);//从顶部(a_T.size==1)开始,向下搜索
int ans = -1e7+5; //答案初始化为负无穷
for (int i = 1; i <= v.size() - 1; i++)
ans = max(ans, v[i].f); //比较各个节点的f值,找出最大的f值
cout << ans << endl; //输出这个最大值
return 0;
}