POJ 1947 Rebuilding Roads (树dp + 背包思想)

Posted Recoder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1947 Rebuilding Roads (树dp + 背包思想)相关的知识,希望对你有一定的参考价值。

题目链接:http://poj.org/problem?id=1947

一共有n个节点,要求减去最少的边,行号剩下p个节点。问你去掉的最少边数。

dp[u][j]表示u为子树根,且得到j个节点最少减去的边数。

考虑两种情况,去掉孩子节点v与去不掉。

(1)去掉孩子节点:dp[u][j] = dp[u][j] + 1

(2)不去掉孩子节点:dp[u][j] = min(dp[u][j - k] + dp[v][k])

综上就是dp[u][j] = min(dp[u][j] + 1, min(dp[u][j - k] + dp[v][k]))

 1 //#pragma comment(linker, "/STACK:102400000, 102400000")
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <ctime>
10 #include <list>
11 #include <set>
12 #include <map>
13 using namespace std;
14 typedef long long LL;
15 typedef pair <int, int> P;
16 const int N = 155;
17 int dp[N][N], n, p, inf = 1e8;
18 vector <int> edge[N];
19 //dp[i][j]表示i为子树根,且得到j个节点最少减去的边数。不考虑父节点
20 
21 void dfs(int u, int par) {
22     for(int i = 2; i <= p; ++i) {
23         dp[u][i] = inf;
24     }
25     dp[u][1] = 0; //考虑到叶子节点,而非叶子节点在下面的for中会增加
26     for(int i = 0; i < edge[u].size(); ++i) {
27         int v = edge[u][i];
28         if(v == par)
29             continue;
30         dfs(v, u);
31         for(int j = p; j >= 1; --j) { 
32         //有点背包的思想,正序的话dp[u][j]可能由dp[v][k]转移而来,在下面会被重复转移。倒序的话保证转移一次。
33             int temp = dp[u][j] + 1; //去掉v子树
34             for(int k = 1; k < j; ++k) {
35                 temp = min(dp[u][j - k] + dp[v][k], temp);
36             }
37             dp[u][j] = temp; //最优 跟最短路思想类似
38         }
39     }
40 }
41 
42 int main()
43 {
44     int u, v;
45     while(~scanf("%d %d", &n, &p)) {
46         for(int i = 1; i <= n; ++i) {
47             edge[i].clear();
48         }
49         for(int i = 1; i < n; ++i) {
50             scanf("%d %d", &u, &v);
51             edge[u].push_back(v);
52             edge[v].push_back(u);
53         }
54         dfs(1, -1);
55         int res = dp[1][p]; //根节点没有父亲 不需要+1
56         for(int i = 2; i <= n; ++i) {
57             res = min(dp[i][p] + 1, res); //其他节点有父节点 去除的话所以+1
58         }
59         printf("%d\n", res);
60     }
61     return 0;
62 }

这题感觉好难想,人笨没办法

以上是关于POJ 1947 Rebuilding Roads (树dp + 背包思想)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1947 Rebuilding Roads

POJ1947 Rebuilding Roads

POJ1947 Rebuilding Roads[树形背包]

[poj 1947] Rebuilding Roads 树形DP

POJ题目1947 Rebuilding Roads(树形dp)

poj1947 Rebuilding Roads