zoukankan      html  css  js  c++  java
  • POJ 1947 Rebuilding Roads

    Rebuilding Roads
     

    Description

    The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The cows didn't have time to rebuild any extra roads, so now there is exactly one way to get from any given barn to any other barn. Thus, the farm transportation system can be represented as a tree. 

    Farmer John wants to know how much damage another earthquake could do. He wants to know the minimum number of roads whose destruction would isolate a subtree of exactly P (1 <= P <= N) barns from the rest of the barns.

    Input

    * Line 1: Two integers, N and P 

    * Lines 2..N: N-1 lines, each with two integers I and J. Node I is node J's parent in the tree of roads. 

    Output

    A single line containing the integer that is the minimum number of roads that need to be destroyed for a subtree of P nodes to be isolated. 

    Sample Input

    11 6
    1 2
    1 3
    1 4
    1 5
    2 6
    2 7
    2 8
    4 9
    4 10
    4 11
    

    Sample Output

    2

    Hint

    [A subtree with nodes (1, 2, 3, 6, 7, 8) will become isolated if roads 1-4 and 1-5 are destroyed.] 
    题意:
    有n个点组成一棵树,问至少要删除多少条边才能获得一棵有p个结点的子树?
    一道转移比较有意思的树形dp题。
    树上的状态应该比较明确。dp[i][j]表示以i为根有j个节点的子树。
    转移怎么办?
    把它的子树编成1,2..x。
    每个子树取几个或不取达到j-1(自己有1个节点)。
    我们好像又能搞出一个dp,
    dp_[i][j]表示前i个子树取了j个节点。
    有dp_[i][j]=min{dp_[i-1][k]+dp[i][j-k]-2};(添加一条边要减2);
    还有dp_[i][j]=min{dp[i-1][k]};
    倒着枚举j。
    可以变成:
    dp_[j]=min(dp_[j],dp_[j-k]+dp[i][j-k]-2);
    直接放在原数组上做:
            for (int j=m;j>1;j--){
                for (int k=1;k<j;k++){
                    dp[u][j]=min(dp[u][j],dp[u][k]+dp[v[i]][j-k]-2);
                }
            }

    代码:

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<cstdlib>
     7 #include<vector>
     8 using namespace std;
     9 typedef long long ll;
    10 typedef long double ld;
    11 typedef pair<int,int> pr;
    12 const double pi=acos(-1);
    13 #define rep(i,a,n) for(int i=a;i<=n;i++)
    14 #define per(i,n,a) for(int i=n;i>=a;i--)
    15 #define Rep(i,u) for(int i=head[u];i;i=Next[i])
    16 #define clr(a) memset(a,0,sizeof(a))
    17 #define pb push_back
    18 #define mp make_pair
    19 #define fi first
    20 #define sc second
    21 #define pq priority_queue
    22 #define pqb priority_queue <int, vector<int>, less<int> >
    23 #define pqs priority_queue <int, vector<int>, greater<int> >
    24 #define vec vector
    25 ld eps=1e-9;
    26 ll pp=1000000007;
    27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
    28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
    29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
    30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; }
    31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
    32 ll read(){ ll ans=0; char last=' ',ch=getchar();
    33 while(ch<'0' || ch>'9')last=ch,ch=getchar();
    34 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    35 if(last=='-')ans=-ans; return ans;
    36 }
    37 const int M=1000,N=200,inf=1e09;
    38 int n,m;
    39 int v[M],Next[M],head[N],e,dp[N][N],du[N];
    40 void add(int x,int y){ v[++e]=y; Next[e]=head[x]; head[x]=e;}
    41 void dfs(int u,int fa){
    42     for (int i=head[u];i;i=Next[i])
    43     if (v[i]!=fa){
    44         dfs(v[i],u);
    45         for (int j=m;j>1;j--){
    46             for (int k=1;k<j;k++){
    47                 dp[u][j]=min(dp[u][j],dp[u][k]+dp[v[i]][j-k]-2);
    48             }
    49         }
    50     }
    51 }
    52 int main(){
    53     n=read(),m=read();
    54     for (int i=1;i<n;i++) {
    55         int a=read(),b=read();
    56         add(a,b); add(b,a);
    57         du[a]++; du[b]++;
    58     }
    59     for (int i=1;i<=n;i++){
    60         dp[i][1]=du[i];
    61         for (int j=2;j<=m;j++) 
    62             dp[i][j]=inf;
    63     }
    64     dfs(1,0);
    65     int ans=inf;
    66     for (int i=1;i<=n;i++)
    67         ans=min(ans,dp[i][m]);
    68     printf("%d",ans);
    69     return 0;
    70 } 
    View Code
  • 相关阅读:
    2.vi 和 vim 编辑器
    1.Linux文件及目录结构
    关于聚集表的学习
    一个完整的表维护程序
    转换函数CONVERSION_EXIT_TSTRN_OUTPUT
    ABAP常用字符串处理
    函数中的异常参数设计
    数据元素文本增强(修改标准数据元素描述)
    锁对象的维护
    在物理表中分配搜索帮助
  • 原文地址:https://www.cnblogs.com/SXia/p/7641038.html
Copyright © 2011-2022 走看看