一、题目
二、分析
dp[i] 第i个节点的子树“美丽指数”之和的最大值
状态转移方程:
(j为i的子节点且dp[j]>0)
第一版思路:
可以采用深度优先搜索求出dp数组,但是无法确定 根节点(必定保留的节点),所以采用循环枚举根节点。
#include <bits/stdc++.h>
using namespace std;
const int N = 200000;
int h[N], e[N * 2], ne[N * 2], idx;
int w[N];
int n;
int dp[N];
bool st[N];
void dfs(int root)
{
int sum=0;
for(int i=h[root];i!=-1;i=ne[i])
{
int j=e[i];
if(!st[j])
{
st[j]=true;
dfs(j);
st[j]=false;
if(dp[j]>0)
sum+=dp[j];
}
}
dp[root]=sum+w[root];
}
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> w[i];
h[i]=-1;
}
for (int i = 1; i < n; i++)
{
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
}
int Max=-(1<<30);
for(int i=1;i<=n;i++)
{
st[i]=true;
dfs(i);
st[i]=false;
Max=max(Max,dp[i]);
}
cout<<Max<<endl;
return 0;
}
很可惜,TLE了
第二版思路:
第一版的dp数组其实只求出一个节点的子树所带来的影响,即下层所带来的影响。故只有最顶层的节点才考虑了其他全部节点对其的影响。所以需要求出各个节点为顶层节点的情况。
如果一个节点能确定上层所带来的影响,那么就省去一层循环。
分析上层带来的影响;
不保留上层:保留该节点的“美丽指数”之和的最大值 = dp[所求节点]
保留上层:
dp[所求节点]<=0:说明dp[父节点]并没有累加所求节点所在的子树的最大“美丽指数”
保留该节点的“美丽指数”之和的最大值 = max(dp[所求节点] , dp[所求节点] + dp[父节点])
dp[所求节点]>0 : 说明dp[父节点]并没有累加所求节点所在的子树的最大“美丽指数”
保留该节点的“美丽指数”之和的最大值 = max(dp[所求节点] ,dp[所求节点] + (dp[父节点] - dp[所求节点]) )= max(dp[所求节点] , dp[父节点] )
三、代码
#include <bits/stdc++.h>
using namespace std;
const int N = 200000;
int h[N], e[N * 2], ne[N * 2], idx;
int w[N];
int n;
int dp[N];
bool st[N];
int Max=-(1<<30);
void dfs(int root)
{
int sum=0;
for(int i=h[root];i!=-1;i=ne[i])
{
int j=e[i];
if(!st[j])
{
st[j]=true;
dfs(j);
st[j]=false;
if(dp[j]>0)
sum+=dp[j];
}
}
dp[root]=sum+w[root];
}
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void dfsMax(int node,int root)
{
Max=max(Max,dp[node]);
if(dp[node]<=0)
Max=max(Max,dp[node]+dp[root]);
else
Max=max(Max,dp[root]);
for(int i=h[node];i!=-1;i=ne[i])
{
int j=e[i];
if(!st[j])
{
st[j]=true;
dfsMax(j,node);
st[j]=false;
}
}
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> w[i];
h[i]=-1;
}
for (int i = 1; i < n; i++)
{
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
}
st[1]=true;
dfs(1);
dfsMax(1,0);
cout<<Max<<endl;
return 0;
}