poj1947Rebuilding Roads(树形DP)

链接

刚接触 树上背包。。有点抽象化 找好父亲和儿子的关系 及状态转移方程 

代码里有详细的注释  就不解释了

 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<stdlib.h>

 6 using namespace std;

 7 #define N 155

 8 #define INF 0xfffffff

 9 int n,m;

10 int w[N][N],o[N],dp[N][N];

11 void add(int u,int v)

12 {

13     w[u][o[u]++] = v;//不在乎内存的邻接表

14 }

15 void dfs(int root)

16 {

17     int i,j;

18     for(i = 0; i <= m ; i++)

19     dp[root][i] = INF;//类似背包的初始化 

20     dp[root][1] = 0;//如果保留一个节点 就不需要切 那个加1 会在后面有

21     for(i = 0; i < o[root] ; i++)

22     {

23         int son = w[root][i];

24         dfs(son);//搜到叶子 树都这样

25         for(j = m ; j>=0 ; j--)

26         {

27             int minz = INF,k;

28             for(k = 0 ; k < j ; k++)

29             minz = min(minz,dp[root][k]+dp[son][j-k]);//这个是对于本儿子来言 找一个能够让父亲保留J个节点的最好办法

30             dp[root][j] = min(dp[root][j]+1,minz);//是保留之前j个节点的取法(就是不要本儿子 切掉) 还是要本儿子的方法

31         }

32     }

33 }

34 int main()

35 {

36     int i;

37     while(scanf("%d",&n)!=EOF)

38     {

39         memset(o,0,sizeof(o));

40         scanf("%d",&m);

41         for(i = 1; i < n ;i++)

42         {

43             int u,v;

44             scanf("%d%d",&u,&v);

45             add(u,v);

46         }

47         dfs(1);

48         int ans = dp[1][m];//树根的话就不用加切祖先那一刀了

49         for(i = 2; i <= n ; i++)

50         ans = min(ans,dp[i][m]+1);//剩下的都要+1

51         cout<<ans<<endl;

52     }

53     return 0;

54 }
View Code

 

你可能感兴趣的:(Build)