• #树形dp#洛谷 1272 重建道路


    题目

    给出一个大小为 (n) 的树,

    问至少断掉多少条边使得存在一个大小为 (m) 的连通块

    (nleq 150)


    分析

    (dp[x][s]) 表示以 (x) 为根的子树至少断掉多少条边使得存在一个大小为 (s) 的连通块

    (dp[x][s]=min{dp[x][s']+dp[y][s-s']})

    如果不选该子树则要多断一条边,最后就是

    (min{dp[x][m]+[x>1]})


    代码

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #define rr register
    using namespace std;
    const int N=161;
    struct node{int y,next;}e[N<<1];
    int siz[N],as[N],dp[N][N],n,m,et=1,ans;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline signed min(int a,int b){return a<b?a:b;}
    inline void dfs(int x,int fa){
    	siz[x]=1,dp[x][1]=0;
    	for (rr int i=as[x];i;i=e[i].next)
    	if (e[i].y!=fa){
    		dfs(e[i].y,x),siz[x]+=siz[e[i].y];
    		for (rr int o=siz[x]-siz[e[i].y];o;--o){
    			for (rr int j=siz[e[i].y];j;--j)
    			    dp[x][o+j]=min(dp[x][o+j],dp[x][o]+dp[e[i].y][j]);
    			++dp[x][o];
    		}
    	}
    }
    signed main(){
    	n=iut(),m=iut(),memset(dp,42,sizeof(dp));
    	for (rr int i=1;i<n;++i){
    	    rr int x=iut(),y=iut();
    	    e[++et]=(node){y,as[x]},as[x]=et;
    	    e[++et]=(node){x,as[y]},as[y]=et;
    	}
    	dfs(1,0),ans=dp[1][m];
    	for (rr int i=2;i<=n;++i) ans=min(ans,dp[i][m]+1);
    	return !printf("%d",ans);
    }
    
  • 相关阅读:
    深入理解link和@import到底有什么区别?
    你应该知道的简单易用的CSS技巧
    META标签的设置
    前端webp图片
    PAT 1130 Infix Expression[难][dfs]
    PAT 1118 Birds in Forest [一般]
    生信-cufflinks输入输出文件分析
    PAT 1121 Damn Single[简单]
    PAT 1049 Counting Ones [难]
    NGS中的一些软件功能介绍
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/15354489.html
Copyright © 2020-2023  润新知