zoukankan      html  css  js  c++  java
  • POJ 1947 Rebuilding Roads(树形DP)

    题目链接

    题意 : 给你一棵树,问你至少断掉几条边能够得到有p个点的子树。

    思路 : dp[i][j]代表的是以i为根的子树有j个节点。dp[u][i] = dp[u][j]+dp[son][i-j]-1,son是u的儿子节点。初始是将所有的儿子都断开,然后-1代表的是这个儿子我需要了,不断了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<iostream>
     5 #define maxn 101
     6 
     7 using namespace std;
     8 
     9 struct node
    10 {
    11     int fa,son,next ;
    12 } pp[210];
    13 int head[210],cnt,root[210],root1,dp[210][210] ;
    14 int p ;
    15 int so[210];//统计儿子的个数
    16 void dfs(int u)
    17 {
    18     for(int i = 0;  i <= p ; i++)
    19         dp[u][i] = 999999999;
    20     dp[u][1] = so[u] ;
    21     for(int ii = head[u] ; ii != -1 ; ii = pp[ii].next)
    22     {
    23         int son = pp[ii].son ;
    24         dfs(son) ;
    25         for(int i = p ; i >= 0 ; i--)
    26         {
    27             int s = dp[u][i] ;
    28             for(int j = 1 ; j < i ; j++)
    29             {
    30                 s = min(s,dp[u][j]+dp[son][i-j]-1) ;
    31             }
    32             dp[u][i] = s ;
    33         }
    34     }
    35 }
    36 void addedge(int u,int v)
    37 {
    38     pp[cnt].fa = u ;
    39     pp[cnt].son = v ;
    40     pp[cnt].next = head[u] ;
    41     head[u] = cnt ++ ;
    42 }
    43 int main()
    44 {
    45     int n,u,v;
    46     while(~scanf("%d %d",&n,&p))
    47     {
    48         cnt = 0 ;
    49         memset(head,-1,sizeof(head)) ;
    50         memset(root,1,sizeof(root)) ;
    51         for(int i = 1 ; i < n ; i++)
    52         {
    53             scanf("%d %d",&u,&v) ;
    54             addedge(u,v) ;
    55             so[u]++;
    56             root[v] = 0 ;
    57         }
    58         for(int i = 1 ; i <= n ; i++)
    59             if(root[i])
    60             {
    61                 root1 = i ;//根节点
    62                 break ;
    63             }
    64         dfs(root1) ;
    65         int ans = dp[root1][p] ;
    66         for(int i = 1 ; i <= n ; i++)
    67             ans = min(ans,dp[i][p]+1) ;
    68         printf("%d
    ",ans) ;
    69     }
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    LeetCode: Number Complement
    LeetCode: Hamming Distance
    LeetCode: Sum of Left Leaves
    LeetCode: Ransom Note
    LeetCode: Minimum Moves to Equal Array Elements
    LeetCode: Linked List Random Node
    LeetCode: Product of Array Except Self
    LeetCode:Two Sum II
    LeetCode: Minimum Moves to Equal Array Elements II
    杂记 -- 时间段内应用程序调用次数限制
  • 原文地址:https://www.cnblogs.com/luyingfeng/p/3956573.html
Copyright © 2011-2022 走看看