• POJ 1947 Rebuilding Roads


    题意:给一棵含有n个节点的树,问最少切割多少条边,能够得到一棵恰好包含p个节点的子树。

    解法:设d[x][i]表示以x为根的子树,切割出含有i个节点的子树最少需要切割多少条边。对于每个子节点y,可以直接将其切掉,也可以对以y为根的树进行切割,然后给以x为根的树增加节点数。这个地方其实就是一个背包,好好体会。

       状态转移方程为d[x][i] = max(d[x][i]+1, d[x][i-j] + d[y][j])。

       注意枚举的时候要逆序,否则要多开一维数组。

    tag:树形dp, 背包

     1 /*
     2  * Author:  Plumrain
     3  * Created Time:  2013-11-19 16:11
     4  * File Name: DP-POJ-1947-2.cpp
     5  */
     6 #include <iostream>
     7 #include <cstdio>
     8 #include <cstring>
     9 #include <vector>
    10 
    11 using namespace std;
    12 
    13 #define CLR(x) memset(x, 0, sizeof(x))
    14 #define PB push_back
    15 const int maxint = 2147483647 / 10;
    16 
    17 int n, p, f;
    18 int d[200][200];
    19 bool vis[200];
    20 vector<int> son[200];
    21 
    22 void init()
    23 {
    24     for (int i = 1; i <= n; ++ i)
    25         son[i].clear();
    26     
    27     CLR (vis);
    28     int t1, t2;
    29     for (int i = 0; i < n-1; ++ i){
    30         scanf ("%d%d", &t1, &t2);
    31         vis[t2] = 1; 
    32         son[t1].PB (t2);
    33     }
    34         
    35     for (int i = 1; i <= n; ++ i)
    36         if (!vis[i]){
    37             f = i; break;
    38         }
    39 }
    40 
    41 void dfs(int x)
    42 {
    43     int sz = son[x].size();
    44     for (int i = 1; i <= p; ++ i)
    45         d[x][i] = maxint;
    46     d[x][1] = 0;
    47 
    48     for (int t = 0; t < sz; ++ t){
    49         int v = son[x][t];
    50         dfs(v);
    51         for (int i = p; i >= 1; -- i){
    52             d[x][i] += 1;
    53             for (int j = 1; j < i; ++ j)
    54                 d[x][i] = min(d[x][i], d[x][i-j] + d[v][j]);
    55         }
    56     }
    57 }
    58 
    59 int main()
    60 {
    61     while (scanf ("%d%d", &n, &p) != EOF){    
    62         init();
    63         
    64         dfs(f);
    65         
    66         d[f][p] -= 1;
    67         int ans = maxint;
    68         for (int i = 1; i <= n; ++ i)
    69             ans = min(ans, d[i][p]);
    70         printf ("%d
    ", ans + 1);
    71     }
    72     return 0;
    73 }
    View Code
    ------------------------------------------------------------------
    现在的你,在干什么呢?
    你是不是还记得,你说你想成为岩哥那样的人。
  • 相关阅读:
    iOS开发之单例模式
    XCode 安装 Alcatraz包管理器失败的处理
    iOS "此证书由未知颁发机构签名"此问题的解决方法
    Android WebView 使用
    BaseActivity
    定时周期执行指定的任务 ScheduledExecutorService
    SQLite数据库浅谈
    android 图片缓存
    Android之drawable state各个属性详解
    Android应用中如何启动另一个应用
  • 原文地址:https://www.cnblogs.com/plumrain/p/POJ_1947.html
Copyright © 2020-2023  润新知