牛客国庆集训派对Day2: H. travel(树形线头DP)

版权声明:本文为博主原创文章,你们可以随便转载 https://blog.csdn.net/Jaihk662/article/details/84330918

链接:https://ac.nowcoder.com/acm/contest/140/H
来源:牛客网

题目描述

White Cloud has a tree with n nodes.The root is a node with number 1. Each node has a value.
White Rabbit wants to travel in the tree 3 times. In Each travel it will go through a path in the tree.
White Rabbit can't pass a node more than one time during the 3 travels. It wants to know the maximum sum value of all nodes it passes through.

输入描述:

The first line of input contains an integer n(3 <= n <= 400001)
In the next line there are n integers in range [0,1000000] denoting the value of each node.
For the next n-1 lines, each line contains two integers denoting the edge of this tree.

输出描述:

Print one integer denoting the answer.

输入

13
10 10 10 10 10 1 10 10 10 1 10 10 10
1 2
2 3
3 4
4 5
2 6
6 7
7 8
7 9
6 10
10 11
11 12
11 13

输出

110

 

题意:

给你一棵n个节点的树,每个点都有一个权值,选出三条不相交路径使得权值和最大

思路:

dp[i][j][0]表示以i为根的子树选了j条路径的最大权值和

dp[i][j][1]表示以i为根的子树选了j条路径,其中一条路径的一端为i的最大权值和

那么dp时来一波类似于背包的转移就好了

//https://ac.nowcoder.com/acm/contest/140/H
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
vector<int> G[500005];
int val[500005];
LL dp[500005][5][2];
void Sech(int u, int fa)
{
	int i, j, p, q, v, t;
	LL now[5][4], c[5][4], sum[5][4];
	memset(now, 0, sizeof(now));
	for(t=0;t<G[u].size();t++)
	{
		v = G[u][t];
		if(v==fa)
			continue;
		Sech(v, u);
		memset(c, 0, sizeof(c));
		for(i=0;i<=3;i++)
			c[i][0] = dp[v][i][0], c[i][1] = dp[v][i][1];
		memset(sum, 0, sizeof(sum));
		for(i=0;i<=3;i++)
		{
			for(j=0;i+j<=3;j++)
			{
				for(p=0;p<=2;p++)
				{
					for(q=0;p+q<=2;q++)
						sum[i+j][p+q] = max(sum[i+j][p+q], now[i][p]+c[j][q]);
				}
			}
		}
		memcpy(now, sum, sizeof(now));
	}
	for(i=0;i<=3;i++)
		dp[u][i][0] = now[i][0];
	for(i=0;i<=2;i++)
	{
		for(j=0;j<=2;j++)
			dp[u][i+1][0] = max(dp[u][i+1][0], now[i][j]+val[u]);
	}
	for(i=0;i<=3;i++)
	{
		for(j=0;j<=1;j++)
			dp[u][i][1] = max(dp[u][i][1], now[i][j]+val[u]);
	}
}
int main(void)
{
	int n, i, x, y;
	scanf("%d", &n);
	for(i=1;i<=n;i++)
		scanf("%d", &val[i]);
	for(i=1;i<=n-1;i++)
	{
		scanf("%d%d", &x, &y);
		G[x].push_back(y);
		G[y].push_back(x);
	}
	Sech(1, 0);
	printf("%lld\n", dp[1][3][0]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Jaihk662/article/details/84330918