• 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
  • 相关阅读:
    成家撑家 不要妄自菲薄
    [文字20091204]佛说贪、嗔、痴、妒、慢、疑
    [文摘20091116]一生必看的88本书
    [文摘201009]演讲录全文:美国世界帝国战略与中国的危机 戴旭
    由 图标 加 文字 实现 按钮功能 的 图标按钮用户控件
    javascript Array扩展
    javascript Number对象
    纯CSS多级菜单2
    纯CSS相册2
    纯CSS多级菜单
  • 原文地址:https://www.cnblogs.com/SXia/p/7641038.html
Copyright © 2020-2023  润新知