The second tree-like DP question, read other people's code, read it for one afternoon to understand, not getting started yet ~
Question:
When there are N points to form a tree, how many sides should be deleted to obtain a subtree with P nodes?
Ideas:
Set DP [I] [k] as the root node and generate a subtree with K nodes. The number of edges to be cut off.
DP [I] [1] = total (I. son) + 1, that is, cut off with all sons (total (I. son), but also cut off the side of his father (+ 1.
DP [I] [k] = min (DP [I] [K], DP [I] [J-K] + dp [I. son] [k]-2), that is. son generates a subtree with K nodes, and then I generates the number of other J-K nodes.
Here we want to restore the edge of I and I. son and his father so-2.
Refer to Daniel's code ~ Start
dp[root][j] = min(dp[root][j], dp[root][j - k] + dp[tree[root][i]][k] - 2);
In-2, always do not understand, not-1 is OK? After a long tangle
For (INT I = 1; I <= N; I ++) {// use I as the root, number of edges to be cut off in a subtree with 1 node. Each node has a parent node + 1 node has a virtual parent node, convenient unified processing of DP [I] [1] = tree [I]. size () + 1; for (Int J = 2; j <= P; j ++) DP [I] [J] = max ;}
dp[root][p]--;
Only then can you understand that the IQ of the cool guys is too high. Worship for a while ~ Later, I thought it over for convenience ~
// AC code:
# Include <iostream> # include <cmath> # include <algorithm> # include <vector> # include <cstdio> # include <cstdlib> # include <cstring> # include <string> using namespace STD; const int max = 10000; vector <int> tree [160]; // set DP [I] [k] to use I as the root, number of edges to be cut off for a subtree with K nodes: int A, B, N, P, DP [160] [160]; bool son [160]; void DFS (INT root) {int Len = tree [root]. size (); For (INT I = 0; I <Len; I ++) {DFS (tree [root] [I]); // recursively call the child node (root traversal) for (Int J = P; j> 1; j --) // The case where J = 1 already exists> 1 can be for (int K = 1; k <j; k ++) DP [root] [J] = min (DP [root] [J], DP [root] [J-K] + dp [tree [root] [I] [k]-2);} int main () {scanf ("% d", & N, & P); memset (son, false, sizeof (son); For (INT I = 0; I <n-1; I ++) {scanf ("% d", & A, & B); tree [A]. push_back (B); son [B] = true; // record whether B has a son} int root = 1; while (son [root]) // find the parent node root ++; For (INT I = 1; I <= N; I ++) {// use I as the root, number of edges to be cut off in a subtree with 1 node. Each node has a parent node + 1 node has a virtual parent node, convenient unified processing of DP [I] [1] = tree [I]. size () + 1; for (Int J = 2; j <= P; j ++) DP [I] [J] = max;} DFS (Root ); DP [root] [p] --; // It is related to + 2 in the DP equation, restoring the edge of I and its father. If I is the parent node,-1 int ans = max; for (INT I = 1; I <= N; I ++) ans = min (ANS, DP [I] [p]); printf ("% d \ n ", ans); Return 0 ;}