P1352 SSL 1607 party without boss (chain forward star)

Keywords: C++ SSL Algorithm Dynamic Programming Graph Theory

Title Description:

Title portal

Problem solving ideas:

According to the meaning of the question, this question is to select several points on a tree to maximize the point weight, in which the selected points meet two conditions:

  1. If the parent node is selected, the child node cannot be selected
  2. If a child node is selected, the parent node cannot be selected

Obviously, the top priority of the problem is how to store a tree or a graph in the program. At this time, the popular adjacency matrix has spatial defects, so we need to use the chain forward star.

Chain forward Star:

Chained forward star is a flexible storage structure. We need to use the structure to implement it in the program.

There is a graph. The relationship between points and edges is:

1 3
2 3
6 4
7 4
4 5
3 5

The actual figure above is:

Set structure array e e e represents the relationship between the midpoint and the edge of the point in the diagram, including h e a d , x , y , n e x t head,x,y,next head,x,y,next, then e . x e.x e.x represents the starting point, e . y e.y e.y represents the target point, e . n e x t e.next e.next means and e . x e.x e.x is the sequence number of the next side of the same starting point, e . h e a d e.head e.head representation e . x e.x e. The sequence number of the first side of X.

As shown in the figure, it is the state when a linked forward star stores a diagram.
We find the starting point No. 4 according to the header e 4 . h e a d = 4 e_4.head=4 e4. head=4 4 4 The first edge with 4 points as the starting point is numbered 4 4 4, the target point of this edge is e 4 . y = 7 e_4.y=7 e4. y=7, i.e. No 7 7 7 points.
Then observe to 4 4 4 as the next edge of the starting point, the number of the edge is e 4 . n e x t = 3 e_4.next=3 e4. next=3, so the number is 3 3 The side of 3 is 4 4 The second side of 4, the target point is e 3 . y = 6 e_3.y=6 e3​.y=6.
If we look at the next side, we find that e 3 . n e x t = 0 e_3.next=0 e3. next=0, that is, there is no next edge, that is, the end pair 4 4 Traversal of 4 points.

Thus, by traversing all the edges of the root node, we can get the child nodes. By repeating this, we can store and traverse a graph.

struct note
{
	int x,y,next;
} e[6010];
int head[6010]={0},tot=0;  //tot represents the number of edges
void add(int x,int y)    //Creates a directed edge between X and Y
{
	tot++;
	e[tot].x=x;
	e[tot].y=y;
	e[tot].next=head[x];
	head[x]=tot;
}

Tree DP:

After solving the problem of storing graphs, we will consider DP on this tree.

set up f i , 1 / 0 f_{i,1/0} fi,1/0 , indicates when considering the second i i When i points are selected / / /When not selected, the i i i is the maximum point weight sum of the subtree of the root.
When the parent node is selected, its child nodes cannot be selected; When the parent node is not selected, its child nodes can also be selected or not selected.

The state transition equation is not difficult to give:
f i = { ∑ j f j , 0 choose The first i individual spot , j by i of son son ∑ j m a x ( f j , 0 , f j , 1 ) no choose The first i individual spot , j by i of son son f_ i=\begin{cases} \sum_ {j}f_ {J, 0} & select the ith point, where j is the son of I \ \ \ \ sum_ {j} Max (f {J, 0}, f {J, 1}) & do not select the ith point, j is the son of I \ end{cases} fi = {∑ J} fj,0 ∑ J} max(fj,0, fj,1) select the ith point, j is the son of i, not the ith point, j is the son of i

Because the tree itself has the nature of recursion, we find a root node, start from the root node, traverse its subtree through the chain forward star, and perform DP recursively.

CODE:

#include <iostream>
#include <cstring>
using namespace std;
struct note
{
	int x,y,next;
} e[6010];
int head[6010]={0},tot=0;
void add(int x,int y)  //Chain forward star
{
	tot++;
	e[tot].x=x;
	e[tot].y=y;
	e[tot].next=head[x];
	head[x]=tot;
}
int n,ri[6010]={0},f[6010][2]={0};
bool vis[6010]={false};
void dp(int s)   //s is the root node of the current tree
{
	f[s][1]=ri[s];
	int i=head[s];   //i is the number of the first side of s
	while(i)
	  {
	  	dp(e[i].y); //Handle the target point of this edge and recurse the subtree
	  	f[s][1]=f[e[i].y][0]+f[s][1];
	  	f[s][0]=max(f[e[i].y][1],f[e[i].y][0])+f[s][0];
	  	i=e[i].next;   //Next edge
	  }
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>ri[i];
	int a,b;
	for(int i=1;i<n;i++)
	  {
	  	cin>>a>>b;
	  	add(b,a);
	  	vis[a]=true;
	  }
	for(int i=1;i<=n;i++)
	  {
	  	if(vis[i]) continue;   //Find the root node, that is, the point with penetration of 0
	  	dp(i);
	  	cout<<max(f[i][1],f[i][0]);
	  	break;
	  }
	return 0;
}

Posted by kir10s on Fri, 03 Dec 2021 18:38:00 -0800