• [luogu]P1272 重建道路[树形DP]


    [luogu]P1272

    重建道路

    ——!x^n+y^n=z^n

    题目描述

    一场可怕的地震后,人们用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)的子树将被分离出来


    很容易想到树形背包,用f[i][j]表示以i为根,删得只剩下j个点的最少删除。

    f[i][j]=Min{f[v][k]+f[i][j-k]-2}(v为i的孩子)[(v,i)应该留下,可两个决策都减了,要-2]。

    初始化:f[i][1]=边数,f[root][1]=边数-1。

    一开始理解错题意,以为root一定要保留,结果就gg了,呵呵。

    代码:

     1 //2017.10.29
     2 //DP
     3 #include<iostream>
     4 #include<cstdio>
     5 #include<cstring>
     6 using namespace std;
     7 inline int read();
     8 int Min(int x,int y){return x<y?x:y;}
     9 namespace lys{
    10     const int N = 150 + 7 ;
    11     struct edge{
    12         int to;
    13         int next;
    14     }e[N*3];
    15     int dp[N][N],pre[N],count[N],fa[N];
    16     int n,p,cnt,ans;
    17     void add(int x,int y){e[++cnt].to=y;e[cnt].next=pre[x];pre[x]=cnt;}
    18     void dfs(int node){
    19         int i,j,k,v;
    20         dp[node][1]=count[node]+(fa[node]!=0);
    21         for(i=pre[node];~i;i=e[i].next){
    22             v=e[i].to;
    23             dfs(v);
    24             for(j=p;j>=2;j--)
    25                 for(k=1;k<j;k++)
    26                     dp[node][j]=Min(dp[node][j],dp[v][k]+dp[node][j-k]-2);
    27         }
    28         ans=Min(dp[node][p],ans);
    29     }
    30     int main(){
    31         int i,u,v;
    32         n=read(); p=read();
    33         memset(pre,-1,sizeof pre);
    34         memset(dp,0x7,sizeof dp);
    35         ans=dp[1][1];
    36         for(i=1;i<n;i++){
    37             u=read(); v=read();
    38             add(u,v);
    39             count[u]++;
    40             fa[v]=u;
    41         }
    42         for(i=1;i<=n;i++) if(!fa[i]){dfs(i);break;}
    43         printf("%d
    ",ans);
    44         return 0;
    45     }
    46 }
    47 int main(){
    48     lys::main();
    49     return 0;
    50 }
    51 inline int read(){
    52     int kk=0,ff=1;
    53     char c=getchar();
    54     while(c<'0'||c>'9'){
    55         if(c=='-') ff=-1;
    56         c=getchar();
    57     }
    58     while(c>='0'&&c<='9') kk=kk*10+c-'0',c=getchar();
    59     return kk*ff;
    60 }
  • 相关阅读:
    搭建Go调试环境(LiteIDE)
    golang编译工具LiteIDE的调试使用方法(F5)
    Golang并发模型:轻松入门流水线FAN模式
    Golang并发中channel的分析
    需求设计说明书的重要性
    Chrome开发者工具详解-Elements、Console、Sources面板
    Chrome开发者工具详解(5)-Application、Security、Audits面板
    bzoj1216: [HNOI2003]操作系统
    bzoj1150: [CTSC2007]数据备份Backup
    bzoj1059: [ZJOI2007]矩阵游戏
  • 原文地址:https://www.cnblogs.com/_inx/p/7751263.html
Copyright © 2020-2023  润新知