题目链接:点击这里
解题思路:
dp[i][0][j] 表示以i为根节点j条不相交路径的最大和
dp[i][1][j] 表示以i为根节点j条+1条一个端点在i的不相交路径的最大和
dp[i][0][j]的转移:
1.儿子的j条不相交路径的最大和
2.儿子的j-1条+2条端点在i的不相交路径
两者取最大即可
dp[i][1][j]的转移:
儿子的j条+1条端点在i的不相交路径
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<set>
#define inf 0x3f3f3f3f
using namespace std;
const int mx = 4e5 + 10;
typedef long long ll;
const int mod = 998244353;
int n,m,a[mx],tot,head[mx];
ll dp[mx][3][4];
struct node
{
int y,nxt;
}edge[mx<<1];
void AddEdge(int x,int y)
{
edge[tot] = {y,head[x]};
head[x] = tot++;
}
void dfs(int x,int fa)
{
ll tem[2][4][4];
memset(tem,0,sizeof(tem));
int id = 0;
for(int i=head[x];~i;i=edge[i].nxt)
{
int v = edge[i].y;
if(v==fa) continue;
dfs(v,x);
for(int i=0;i<=2;i++){
for(int j=0;i+j<=2;j++){
for(int p=0;p<=3;p++){
for(int q=0;q+p<=3;q++){
tem[id][i+j][p+q] = max(tem[id][i+j][p+q],tem[id^1][i][p]+dp[v][j][q]);
}
}
}
}
id ^= 1;
}
for(int i=1;i<=3;i++) dp[x][0][i] = max(dp[x][0][i],tem[id^1][0][i]);
for(int i=1;i<=3;i++) dp[x][0][i] = max(dp[x][0][i],tem[id^1][2][i-1]+a[x]);
for(int i=0;i<=3;i++) dp[x][1][i] = max(dp[x][1][i],tem[id^1][1][i]+a[x]);
}
int main()
{
while(~scanf("%d",&n))
{
int x,y;
memset(head,-1,sizeof(head));
tot = 0;
for(int i=1;i<=n;i++) scanf("%d",a+i);
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
AddEdge(x,y);
AddEdge(y,x);
}
dfs(1,0);
printf("%lld\n",dp[1][0][3]);
}
return 0;
}