zoukankan      html  css  js  c++  java
  • P1272 重建道路

    P1272 重建道路

    题目描述

    一场可怕的地震后,人们用N个牲口棚(1≤N≤150,编号1..N)重建了农夫John的牧场。由于人们没有时间建设多余的道路,所以现在从一个牲口棚到另一个牲口棚的道路是惟一的。因此,牧场运输系统可以被构建成一棵树。John想要知道另一次地震会造成多严重的破坏。有些道路一旦被毁坏,就会使一棵含有P(1≤P≤N)个牲口棚的子树和剩余的牲口棚分离,John想知道这些道路的最小数目。

    输入输出格式

    输入格式:

    第1行:2个整数,N和P

    第2..N行:每行2个整数I和J,表示节点I是节点J的父节点。

    输出格式:

    单独一行,包含一旦被破坏将分离出恰含P个节点的子树的道路的最小数目。

    输入输出样例

    输入样例#1:
    11 6
    1 2
    1 3
    1 4
    1 5
    2 6
    2 7
    2 8
    4 9
    4 10
    4 11
    
    输出样例#1:
    2
    

    说明

    【样例解释】

    如果道路1-4和1-5被破坏,含有节点(1,2,3,6,7,8)的子树将被分离出来

    分析:

    用 dp[i][j] 表示以i节点为根,截出含有j个点的连通子树所需要截的最少次数。

    那么可以得到初始化 dp[i][1]=du[i] (du[i]为i的入边与出边的总和),意思是只选i这一个节点,那么当然要把与它相连的边都截掉。

    那么状态转移方程怎么得到呢

    以样例为例子,节点1连接 2,3,4,5 。节点2连接 6,7,8。递归着进行动规之后我们可以得到 dp[2][3]=2 (截取1-2和2-8)

    那么dp[1][4]=min(dp[1][4],dp[2][3]+dp[1][1]-2)

    为啥要减2

    因为dp[1][1]是删了一次 1-2 的结果,dp[2][3]也删了一次 1-2,但事实上得到dp[1][4]时 1-2是连通的,所以把这删的两次补上。

    具体动规按照分组背包的循环顺序跑。

    状态转移方程:

    dp[u][j]=min(dp[u][j],dp[u][k]+dp[v][j-k]-2);

    从父亲节点选k个,从儿子节点选j-k个。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<vector>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define ll long long
     7 #define M(a) memset(a,0,sizeof a)
     8 #define fo(i,j,k) for(i=j;i<=k;i++)
     9 using namespace std;
    10 const int mxn=155;
    11 vector <int> f[mxn];
    12 int n,p;
    13 int dp[mxn][mxn],du[mxn];
    14 inline void dfs(int u)
    15 {
    16     int i,j,k,v,x=f[u].size()-1;
    17     //包含出度和入度 
    18     dp[u][1]=du[u];
    19     fo(i,0,x)
    20     {
    21         v=f[u][i];
    22         dfs(v);
    23         for(j=p;j>=2;j--)
    24           for(k=1;k<j;k++)
    25             dp[u][j]=min(dp[u][j],dp[u][k]+dp[v][j-k]-2);
    26     }
    27 }
    28 int main()
    29 {
    30     int i,j,u,v,ans=1e8;
    31     scanf("%d%d",&n,&p);
    32     fo(i,0,n) fo(j,0,n) dp[i][j]=200; //初始化防止加法溢出 
    33     fo(i,0,n) dp[i][0]=0;
    34     fo(i,2,n)
    35     {
    36         scanf("%d%d",&u,&v);
    37         f[u].push_back(v);
    38         du[u]++;du[v]++;
    39     }
    40     dfs(1);
    41     fo(i,1,n)
    42       ans=min(ans,dp[i][p]);
    43     printf("%d
    ",ans);
    44     return 0;
    45 }
  • 相关阅读:
    Spring spEL
    Spring 使用外部部署文件
    Spring 自动装配
    spring 属性配置细节
    hdu 1054 Strategic Game
    fzu 2037 Maximum Value Problem
    将博客搬至CSDN
    HDU 4714 Tree2Cycle
    HDU 1009 The Shortest Path in Nya Graph
    POJ 1942 Paths on a Grid 组合数的优化
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/7482743.html
Copyright © 2011-2022 走看看