• 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
  • 相关阅读:
    使用ExcelMapper制作用于打印的矩阵
    八皇后问题-回溯法解
    HashMap-1.8 你看得懂的原理分析
    一生之敌
    必学十大经典排序算法,看这篇就够了(附完整代码/动图/优质文章)
    事务的四种隔离级别
    数据库的三范式
    ConcurrentHashMap底层实现原理和源码分析
    leetcode-160-相交链表(simple)
    JAVA中priorityqueue详解
  • 原文地址:https://www.cnblogs.com/SXia/p/7641038.html
Copyright © 2020-2023  润新知