POJ 1947 Rebuilding Roads

大概的题意是给出n,p,一共有n个节点,问你要剩下p个节点,最少减去最少的边是多少。
dp[root][i]:记录root结点,要得到一棵i个节点的子树去掉的最少边数

详细解释看代码:

 1 #include<cstdio>

 2 #include<iostream>

 3 #include<cstring>

 4 using namespace std;

 5 #define N 160

 6 #define INF 0x3ffffff

 7 

 8 int dp[N][N],son[N],bro[N],fa[N];

 9 int root,n,p;

10 

11 void dfs(int root)

12 {

13     int tem;

14     for(int i=0; i<=p; i++)

15         dp[root][i] = INF;

16 

17     dp[root][1] = 0;//在root处想得到[i]个节点的子树所要去掉的最少边数

18     int k = son[root];//考虑其儿子k

19 /*

20 切去k子树:tem = dp[root][i] + 1

21 不切掉k子树:tem = min(dp[k][i-j]+dp[root][j],tem)

22 */

23     while(k)

24     {

25         dfs(k);

26         for(int i=p; i>=1; i--)//类似背包的处理

27         {

28             tem = dp[root][i] + 1;//在root处想得到i个节点子树时,进行剪掉子树

29 

30             for(int j=1; j<i; j++)

31                 tem = min(dp[k][i-j]+dp[root][j],tem);//不剪去第k个子树,然后的到所需节点数的边数dp[k][i-j]+dp[root][j]

32 

33             dp[root][i] = tem;

34         }

35         k = bro[k];

36     }

37 }

38 

39 int solve()

40 {

41     dfs(root);

42     int ans = dp[root][p];

43     for(int i=1; i<=n; i++)

44         ans = min(dp[i][p]+1,ans);

45     printf("%d\n",ans);

46     return ans;

47 }

48 int main()

49 {

50     //freopen("in.txt","r",stdin);

51     int a,b;

52     while(~scanf("%d%d",&n,&p) )

53     {

54         memset(fa,0,sizeof(fa));

55         memset(son,0,sizeof(son));

56         //memset(brother,0,sizeof(brother));

57 

58         for(int i=1; i<n; i++)

59         {

60             scanf("%d%d",&a,&b);//brother[i]记录i节点的儿子数,brother[i]记录i节点的兄弟数

61             fa[b] = 1;//标记有父亲不是根

62             bro[b] = son[a];//记录同一个父亲的上一个兄弟

63             son[a] = b;//该父亲现在的儿子

64         }

65         /*

66         for(int i=1; i<12; i++)

67         {

68             printf("~~fa[%d]=%d  ",i,fa[i]);

69             printf("~~bro[%d]=%d  ",i,bro[i]);

70             printf("~~son[%d]=%d\n",i,son[i]);

71         }

72         */

73         for(int i=1; i<=n; i++)//找到根节点

74         {

75             if(fa[i] == 0)

76             {

77                 root = i;

78                 break;

79             }

80         }

81 

82         solve();

83     }

84     return 0;

85 }

 

你可能感兴趣的:(Build)