/*
This problem is also good, I have come up with the idea of a relatively fast, also came to a small experience, after writing this problem first to write the key part of the pseudo-code to write this will be much faster and
Not so easy to make mistakes, save a lot of debugging time
The problem is to transform it into a tree-shaped backpack. First, the need to pay the money to a negative number, each leaf node to add a child nodes to make money, positive.
Then record the amount of money that is spent on all possible users of the current node. So the problem turns into a simple tree DP problem. Finally find out the biggest profit for non-negative
Number of users.
One thing to note is that the DP array is initialized to a very large negative number, just starting with this question WA again
The number of leaf nodes that the NUM array holds for each node is used to optimize the function.
*/
#include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <iostream >using namespace std; #define MAXN 6005int dp[maxn][maxn],num[maxn],val[maxn];vector<int>sons[maxn];// Num plays a significant role in optimizing the number of leaf nodes in the current node tree, void DFS (int rt) {dp[rt][0]=0; for (int u=0;u<sons[rt].size (); u++) {int s=sons[rt][u]; DFS (s); Num[rt]+=num[s]; for (int i=num[rt]-num[s]+1;i<=num[rt];i++) dp[rt][i]=-1000000; To initialize to a large negative number for (int i=num[rt];i>=1;i--) {for (int j=1;j<=num[s]&&j<=i;j++) { Dp[rt][i]=max (Dp[rt][i],dp[s][j]+dp[rt][i-j]+val[s]); }}}}void init () {for (int i=0;i<maxn;i++) sons[i].clear (); Memset (Val,0,sizeof (Val)); memset (num,0,sizeof (num));} void print () {for (int i=num[1];i>=0;i--) if (dp[1][i]>=0) {printf ("%d\n", I); int main () {int i,j,n,m,k,a,b; while (~SCANF ("%d%d", &n,&m)) {init (); FoR (i=1;i<=n-m;i++) {scanf ("%d", &k); for (j=1;j<=k;j++) {scanf ("%d%d", &a,&b); Sons[i].push_back (a); Val[a]=-b; }} for (i=n+1;i<=n+m;i++) {//Add a node to each leaf node and use it to represent the money earned, while other points indicate the amount of money to be paid scanf ("%d", &val[i]) ; Num[i]=1; Sons[i-m].push_back (i); } dfs (1); Print (); } return 0;}
POJ 1155 TELE (tree-shaped generalized backpack DP)