DP study notes on the tree

Tree DP:

The problems faced by linear dp are generally linear sequences or graphs.

Tree dp is a kind of dp on a tree structure, and tree dp can also be used when each stage presents a tree relationship.

Tree dp process:

1. If the problem is a recessive tree (i.e. without the tree as a direct background), the problem needs to be transformed into a dominant tree and the tree-like connections of each stage are stored.

2. dp is performed on the data structure of the tree, but its solution is different from linear dp:

The calculation order is different. Linear dp has two directions, forward and reverse; and tree dp also has two directions. The pre-root traversal from root to leaf is not commonly used. Generally, we use post-root traversal from leaf to root, that is, the child node transmits useful information to the parent node, pushes up layer by layer, and finally obtains the optimal solution from the root.

The calculation method is different.    The traditional iteration is used linearly, and the tree shape is memorized and recursive.

Example question above:

P1352 Prom without a boss:

Topic description

A university has N staff, numbered 1~N. There is a subordinate relationship between them, that is to say, their relationship is like a tree with the principal as the root, and the parent node is the direct boss of the child node. Now there is an anniversary banquet. Every time a staff member is invited to the banquet, a certain happiness index Ri will increase. However, if the boss of a staff member comes to the dance party, then the staff member will not come to the dance party anyway. So, please program and calculate, which staff can be invited to maximize the happiness index, and find the maximum happiness index.

Input and output format

Input format:

The first line contains an integer N. (1<=N<=6000)

Next N lines, the i+1th line represents the happiness index Ri of employee i. (-128<=Ri<=127)

Next N-1 lines, each line input a pair of integers L, K. Indicates that K is L's direct boss.

Enter 0 0 on the last line

Output format:

Output the maximum happiness index.

Input and output example



Input Example #1:   Copy
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
Output Sample #1:   Copy
5















This question is actually a recessive tree rooted at the top boss. For any branch node u in the tree, the maximum happiness index sum of the subtree rooted by it may have two possible values.

If the maximum happiness index of the subtree and the happiness index that does not contain u, that is, the person does not participate, then the maximum happiness index sum of the subtree is the maximum of all subtrees of u (subtrees rooted at the son of u) The accumulation of happiness index. Therefore, the maximum happiness index sum of each subtree is the largest among the sons that contain u or the sons that do not contain u.

If the maximum happiness index of the subtree and the happiness index including u, that is, the person participates, his subordinates (subtrees) cannot participate.

dp[u][0] is the maximum happiness index sum of the subtree rooted at u, excluding u.

dp[u][1] is the maximum happiness index sum of the subtree including u and taking u as the root.

Obvious: dp[u][0]=0,dp[u][1]=u;

Starting from the leaf nodes, traverse dp in post-order from bottom to top

equation:

dp[u][0]=      Σ     max{dp[i][0],dp[i][1]}

                The set of sons of i ∈ u

dp[u][1]=dp[u][1] (that is, the happiness index of u)+dp[u][0]

The final result is ans=max{dp[root][0],do[root][1]}

Above code:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
int N,r[10001],a,b,root;
int dp[10001][2],son[10001],bro[10001];
bool is_son[10001];
void DP(int u){
	dp[u][0]=0;
	dp[u][1]=r[u];
	for(int i=son[u];i!=0;i=bro[i]){
		DP(i);//Recursive implementation of post-order traversal
		dp[u][0]+=max(dp[i][0],dp[i][1]);
		dp[u][1]+=dp[i][0];
	}
}
int main(){
	cin>>N;
	memset(son,0,sizeof(son));
	memset(is_son,0,sizeof(is_son));
	for(int i=1;i<=N;i++){
		cin>>r[i];
	}
	for(int i=1;i<N;i++){
		cin>>a>>b;
		bro[a]=son[b];//Adjacency list
		son[b]=a;//a is a subordinate of b
		is_son[a]=true;//Mark a with a boss
	}
	for(int i=1;i<=N;i++){
		if(!is_son[i]) root=i;//Traverse it to find the root node
	}
	DP(root);
	cout<<max(dp[root][0],dp[root][1]);
	return 0;
}


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324792909&siteId=291194637