Tree DP Summary, continuous update __ Blog

Source: Internet
Author: User

I have done the dynamic planning of the topic has been one months, but the results are very little, so to summarize the dynamic planning, I hope I can restudying. This blog is about the tree DP, the dynamic programming of a class of topics.
first of all, starting with the simplest tree DP, the tree DP is the name of a tree and dynamic planning combined, I did the 7,8 problem tree dp, so far found that the tree DP code style are similar, are in the process of the Dfs tree DP.
First look at a simple getting Started topic
The question is in a tree, select some nodes each node can be the regulator to connect their own side, ask at least how many nodes can be selected to allow all sides are regulated.
Idea: 1: node states can be divided into take and not take, so use a two-dimensional array to represent the state of the node. 2: If the current node is selected, the child nodes may or may not be selected, but if the current node is not selected, the child node must be selected. The
state transition equation is shown in the code

#include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <
Stdlib.h> using namespace std;
#define MAX 1500 int n;
int root;
int tot;
    struct Node {int value;
int next;
}EDGE[MAX*2+5];
int head[max+5];
int dp[max+5][2];
int vis[max+5];
    void Add (int x,int y) {edge[tot].value=y;
    EDGE[TOT].NEXT=HEAD[X];
head[x]=tot++;
    } void Dfs (int root) {dp[root][0]=0;
    Dp[root][1]=1;
    Vis[root]=1;
        for (int i=head[root];i!=-1;i=edge[i].next) {int k=edge[i].value;
            if (!vis[k]) {DFS (k);
            State transition equation dp[root][0]+=dp[k][1];
    Dp[root][1]+=min (dp[k][0],dp[k][1]);} int main () {int a,b;
    int m;
        while (scanf ("%d", &n)!=eof) {tot=0;
        memset (Vis) (vis,0,sizeof);
        Memset (head) (head,-1,sizeof);
        Memset (Dp,0,sizeof (DP)); for (int i=0;i<n;i++) {scanf ("%d: (%d)", &a,&m);
            if (i==0) root=a;
                for (int j=0;j<m;j++) {scanf ("%d", &b);
                Add (a,b);
            Add (B,a);
        } dfs (root);
    printf ("%d\n", Min (dp[root][0],dp[root][1));
return 0;

 }

This is an introductory topic, so look at a topic that is very similar to it and just change it a little bit.
State transition equation See Code
(http://acm.hdu.edu.cn/showproblem.php?pid=1520)

#include <iostream> #include <string.h> #include <algorithm> #include <math.h> #include <
Stdlib.h> using namespace std;
    #define MAX 6000 struct Node {int value;
int next;
}EDGE[MAX*2+5];
int tag[max+5];
int dp[max+5][2];
int n;
int root;
int tot;
int rat[max+5];
int head[max+5];
int vis[max+5];
    void Add (int x,int y) {edge[tot].value=y;
    EDGE[TOT].NEXT=HEAD[X];
head[x]=tot++;
    } void Dfs (int root) {Dp[root][1]=rat[root];
    dp[root][0]=0;
    Vis[root]=1;
        for (int i=head[root];i!=-1;i=edge[i].next) {int k=edge[i].value;
            if (!vis[k]) {DFS (k);
            State transition equation Dp[root][1]+=dp[k][0];
        Dp[root][0]+=max (dp[k][0],dp[k][1]);
    int main () {int a,b;
        while (scanf ("%d", &n)!=eof) {tot=0;
        Memset (head) (head,-1,sizeof);
        Memset (Dp,0,sizeof (DP));
        memset (Vis) (vis,0,sizeof);
     memset (tag,0,sizeof (tag));   for (int i=1;i<=n;i++) {scanf ("%d", &rat[i]);
        } scanf ("%d%d", &a,&b);
            while (a!=0&&b!=0) {tag[a]=1;
            Add (B,a);
            Add (a,b);
        scanf ("%d%d", &a,&b);
              for (int i=1;i<=n;i++) {if (tag[i]==0) {root=i;
            Break
        } dfs (1);
    printf ("%d\n", Max (dp[1][0],dp[1][1));
return 0;

 }

These two topics can be said to be a type, are selected in the tree some nodes to obtain the optimal value, the restriction is the child node and the parent node relationship, both can not be selected, or can not be selected, so the code is almost the same.
Next look at a problem that is harder than before
(http://acm.hdu.edu.cn/showproblem.php?pid=1561)
Question: There are n castles forming a tree, you can only attack M castle, Each castle has a corresponding treasure, to conquer these castles must first conquer the other a particular castle, that is, first to conquer the root, before you can attack the subtree down, ask can get the greatest treasures.
thought: This topic differs from the front, there are two restrictions, one must learn to conquer the parent node to attack the child node, the other is only to conquer M castle. Here you can see that the tree DP and the dependency backpack are a little bit similar. In fact, to solve the problem of relying on knapsack, it is to use the idea of the tree DP, first solve the optimal solution of the subtree, and then get the optimal solution of the root. The process is from the bottom up, and the tree Dfs is to search the leaf node first, and then layer up, constantly update the optimal node, the ultimate guarantee that the value of the root node is optimal. The state transition equation is shown in the code

#include <iostream> #include <string.h> #include <algorithm> #include <stdlib.h> #include <
Math.h> using namespace std;
    #define MAX struct Node {int value;
int next;
}EDGE[MAX+5];
int tot;
int head[max+5];
int n,m;
int num[max+5];
int dp[max+5][max+5];
int vis[max+5];
     void Add (int x,int y) {edge[tot].value=y;
     EDGE[TOT].NEXT=HEAD[X];
head[x]=tot++;
    } void Dfs (int root,int tag) {vis[root]=1;
    Dp[root][1]=num[root];
        for (int i=head[root];i!=-1;i=edge[i].next) {int t=edge[i].value;
        if (!vis[t]) {DFS (t,tag-1);
                 for (int j=tag;j>=1;j--) {for (int k=1;k<j;k++) {//state transfer equation
             Dp[root][j]=max (Dp[root][j],dp[root][j-k]+dp[t][k]);
    int main () {int A;
        while (scanf ("%d%d", &n,&m)!=eof) {if (n==0&&m==0) break;
    tot=0;    Memset (head) (head,-1,sizeof);
        Memset (Dp,0,sizeof (DP));
        memset (Vis) (vis,0,sizeof);
            for (int i=1;i<=n;i++) {scanf ("%d%d", &a,&num[i]);
        Add (a,i);
        DFS (0,M+1);
    printf ("%d\n", dp[0][m+1]);
return 0; }

The

code understands and is well understood, and then look at an updated version of the problem (http://acm.hdu.edu.cn/showproblem.php?pid=1011)
: As mentioned above, the change is that each node is conquered and the number of different soldiers is required.

Main.cpp//Tree DP2////Created by Chen Yongkang on 16/1/3. Copyright (c) 2016 Chen Yongkang.
All rights reserved. #include <iostream> #include <string.h> #include <algorithm> #include <math.h> #include <s
Tdlib.h> using namespace std;
int dp[105][105];//The current node is I, the number of the soldier is J to get the maximum energy value int n,m;
int bug[105];
int brain[105];
int head[105];
int tot;
int vis[105];
    struct Node {int value;
int next;
}EDGE[105*2];
    void Add (int x,int y) {edge[tot].value=y;
    EDGE[TOT].NEXT=HEAD[X];
head[x]=tot++;
    } void Dfs (int root,int tag) {vis[root]=1;

        int term= (bug[root]+19)/20;
    Dp[root][term]=brain[root];
        for (int i=head[root];i!=-1;i=edge[i].next) {int u=edge[i].value;

            if (!vis[u]) {DFS (u,tag-term);
                    for (int j=tag;j>=term;j--) {for (int k=1;j+k<=m;k++) { if (Dp[u][k]) Dp[root][j+k]=max (dp[root][j+k],dp[Root][j]+dp[u][k]);
    int main () {int x,y;
        while (scanf ("%d%d", &n,&m)!=eof) {if (n==-1&&m==-1) break;
        memset (Vis) (vis,0,sizeof);
        Memset (head) (head,-1,sizeof);
        tot=0;
        Memset (Dp,0,sizeof (DP));
        for (int i=1;i<=n;i++) {scanf ("%d%d", &bug[i],&brain[i]);
            for (int i=1;i<n;i++) {scanf ("%d%d", &x,&y);
            Add (x,y);
        Add (y,x);
        DFS (1,M);
        if (m==0) printf ("0\n");
    else printf ("%d\n", Dp[1][m]); }
}
 It is worth noting that there is another AC code, which is a little different from the above 
#include <iostream> #include <string.h> #include <algorithm> #include <math.h> #include <
Stdlib.h> using namespace std;
int dp[105][105];//The current node is I, the number of the soldier is J to get the maximum energy value int n,m;
int bug[105];
int brain[105];
int head[105];
int tot;
int vis[105];
    struct Node {int value;
int next;
}EDGE[105*2];
    void Add (int x,int y) {edge[tot].value=y;
    EDGE[TOT].NEXT=HEAD[X];
head[x]=tot++;
    } void Dfs (int root) {vis[root]=1;
    int term= (bug[root]+19)/20;
    for (int i=term;i<=m;i++) dp[root][i]=brain[root];
        for (int i=head[root];i!=-1;i=edge[i].next) {int u=edge[i].value;

            if (!vis[u]) {DFS (U);
                     for (int j=m;j>=term;j--) {for (int k=1;j+k<=m;k++) {
                 if (Dp[u][k]) Dp[root][j+k]=max (dp[root][j+k],dp[root][j]+dp[u][k]);
   int main () {int x,y; WhiLe (scanf ("%d%d", &n,&m)!=eof) {if (n==-1&&m==-1) break;
       memset (Vis) (vis,0,sizeof);
       Memset (head) (head,-1,sizeof);
       tot=0;
       Memset (Dp,0,sizeof (DP));
       for (int i=1;i<=n;i++) {scanf ("%d%d", &bug[i],&brain[i]);
           for (int i=1;i<n;i++) {scanf ("%d%d", &x,&y);
           Add (x,y);
       Add (y,x);
       DFS (1);
       if (m==0) printf ("0\n");
   else printf ("%d\n", Dp[1][m]); }
}

This code does not like the previous, DFS and the current node can be used by the number of soldiers, it seems to write this does not reflect to attack the child node must conquer the parent node of this restriction, but it is true. My guess is that this is two different ways to plan, the first way, you can hit a DP two-dimensional array of tables, found that it is a strict from the root node down, must meet the parent node is conquered, the child nodes can have the optimal value. And the second way, you can find that its DP two-dimensional array table, is based on each node as the root nodes to get the optimal value of the knot. That is, when I plan to this node, without having to manage its parent node, he is the root. So back to the root node, still can be guaranteed to attack the child node must conquer the parent node of this restriction, the final value is correct. If this is the case, you can select a node as the root, and go on to attack. Then the second solution satisfies the
next, or this type of topic but more difficult,
(http://acm.hdu.edu.cn/showproblem.php?pid=4169)
The question: The difference between this topic and the previous topic is that we have to attack the child node must conquer the parent node this restriction condition removed. Plus one, child nodes and parent nodes cannot coexist. And the node has 1500000, so you use a DP array to indicate that the state of the node is definitely blown. The key is how to set the DP array, I do not see the blog accept this topic, is to be very familiar with dynamic planning. State transition equation See the code, I wrote my understanding in the comments.

#include <iostream> #include <string.h> #include <algorithm> #include <math.h> #include <
Stdlib.h> using namespace std;
#define MAX 1500000 int v[max+5];
int head[max+5];
int dp[305];
int n;
int tot;
int m;
    struct Node {int value;
int next;
}EDGE[MAX+5];
    void Add (int x,int y) {edge[tot].value=y;
    EDGE[TOT].NEXT=HEAD[X];
head[x]=tot++;
    int dfs (int root) {int t=0;
    int tag=0;
    int cur[305];//This array is constantly replaced for (int i=0;i<=m;i++) dp[i]=cur[i]=-1;
    dp[0]=cur[0]=0;
        for (int i=head[root];i!=-1;i=edge[i].next) {tag=1;
        int k=edge[i].value;
        Get the state number of the subtree int state=dfs (k);
                    for (int j=t;j>=0;j--) {for (int p=1;p<=state;p++) {if (p+j>m)
                Break
            Cur[p+j]=max (Cur[p+j],dp[p]+cur[j]);
    }} t+=state;
    } if (!tag) t++;
    Cur[1]=max (Cur[1],v[root]); The current childThe state of the tree is saved to the DP array, where the DP array represents the optimal value of the current tree, and the cur array is for (int i=0;i<=m;i++) dp[i]=cur[i];
return t;
    int main () {int A;
    int root;
        while (scanf ("%d%d", &n,&m)!=eof) {memset (head);
        tot=0;
            for (int i=1;i<=n;i++) {scanf ("%d%d", &a,&v[i]);
            if (a==0) root=i;
        Add (a,i);
        DFS (root);
        if (dp[m]==-1) printf ("impossible\n");

    else printf ("%d\n", Dp[m]);
return 0; }

This topic defines two state arrays, cur[],dp[]. Dp[] contains the final answer, Cur[] is a temporary array representing the state of the subtree.
See another topic of different styles
(http://acm.hdu.edu.cn/showproblem.php?pid=2412)
This topic is very similar to the previous one, but a little different, It asks if the optimal value is only a combination. The solution to this problem is to open an array of States to indicate that the current optimal value is not unique, and if you can think of it, the problem is solved.

 #include <iostream> #include <string.h> #include <math.h> #include <
stdlib.h> #include <algorithm> #include <map> #include <string> using namespace std;
#define MAX map<string,int>m;
int n;
String a,b;
int tot;
int head[max+5];
int dp[max+5][2];
int dup[max+5][2];
BOOL tag;
    struct Node {int value;
int next;
}EDGE[MAX*2+5];
    void Add (int x,int y) {edge[tot].value=y;
    EDGE[TOT].NEXT=HEAD[X];
head[x]=tot++;
      } void Dfs (int root) {dp[root][1]=1;
      dp[root][0]=0;
      Dup[root][1]=1;
      Dup[root][0]=1;
          for (int i=head[root];i!=-1;i=edge[i].next) {int k=edge[i].value;
          DFS (k);
          DP[ROOT][1]+=DP[K][0];
          Dp[root][0]+=max (dp[k][0],dp[k][1]); if (dp[k][1]<dp[k][0]&&dup[k][0]==0) dup[root][0]= 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.