[Usaco2002 Feb]Rebuilding Roads重建道路
题目描述
一场可怕的地震后,奶牛用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个节点的子树的道路的最小数目。
直观的做法就是去掉一些点之后有没有出现大小为P的连通块。可以用暴搜来完成这个算法,但复杂度是不可接受的O(2^N * N)。如果记忆化应该能过,但代码不好写。
分析题目。我们发现要让整棵树一下断出一个大小为P的连通块是很难的。但是好在我们可以多次断点。如果我们断掉若干个点,断去这些点都会给连通块减少一点大小,我们是一定可以得到想要的连通块的。所以这题的重点就在于一个点断不断的选择上。
根据刚才"凑出P个点"的思想,我们可以设计出状态:dp(i,j)表示以i为根的子树中断掉j个点的最少次数。由于牧场是一棵树,最小值显然具有传递性。设节点u有k个儿子,并且设以节点u为根的子树的大小为size(u),那么传递性具体用状态转移方程表示就是:
\]
由于在枚举到son(x)之前我们已经处理了若干个u的儿子,你可以理解为:在处理son(x)之前u的子树中添加了一棵新的son(x)的子树。那么加号前面就可以理解为:在son(x)之前的子树中断i-j个点,再在son(x)的子树中断j个点。
考虑边界情况。
显然dp(u,0)=0,dp(u,size(u))=1。第二句表示把整棵u的子树都断掉,那么只需要断掉u和其父亲节点的连线即可。
边界情况告诉我们,在计算dp数组前我们就需要求出size数组。所以这道题需要两次dfs来完成:一个求size,一个求dp。
然后我们枚举每个节点,考虑以这些点为根的所有子树来计算答案。假设答案就是在节点i的子树中断掉一些点而形成,那么答案就是dp(i,size(i)-q)+dp(i,size(i))。加上后一项的原因是我们考虑答案就在i的子树中,所以我们要把i和其父亲断开。然后枚举每个i,求最小值即可。
需要注意的细节有:
1.默认根节点为1,那么初始化时dp(1,size(1))应等于0,因为它没有父亲。
2.最后统计答案时应注意size(i)≥q。
时间复杂度为O(N^2 * Q)
* 代码中用m代替了q(个人习惯)
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 151
#define maxm 21
using namespace std;
struct edge{
int to,next;
edge(){}
edge(const int &_to,const int &_next){ to=_to,next=_next; }
}e[maxn<<1];
int head[maxn],k;
int dp[maxn][maxn],size[maxn];
int n,m;
inline int read(){
register int x(0),f(1); register char c(getchar());
while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
inline void add(const int &u,const int &v){ e[k]=edge(v,head[u]),head[u]=k++; }
void dfs1(int u,int pre){
size[u]=1;
for(register int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(v==pre) continue;
dfs1(v,u);
size[u]+=size[v];
}
dp[u][0]=0,dp[u][size[u]]=1;
}
void dfs2(int u,int pre){
for(register int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(v==pre) continue;
dfs2(v,u);
for(register int i=size[u]-1;i>=1;i--){
for(register int j=0;j<=i;j++){
dp[u][i]=min(dp[u][i],dp[u][i-j]+dp[v][j]);
}
}
}
}
int main(){
memset(head,-1,sizeof head);
n=read(),m=read();
for(register int i=1;i<n;i++){
int u=read(),v=read();
add(u,v),add(v,u);
}
memset(dp,0x3f,sizeof dp);
dfs1(1,0),dp[1][n]=0,dfs2(1,0);
int ans=0x3f3f3f3f;
for(register int i=1;i<=n;i++) if(size[i]>=m) ans=min(ans,dp[i][size[i]-m]+dp[i][size[i]]);
printf("%d\n",ans);
return 0;
}
[Usaco2002 Feb]Rebuilding Roads重建道路的更多相关文章
- 【USACO02FEB】Rebuilding Roads 重建道路 题解(树形DP)
题目链接 题目大意:问使含有$p$个节点的子树分离至少需要去掉几条边. ------------------ 设$f[i][j]$表示以$i$为根的子树保留$j$个节点所去掉的最少边数. 初始化$f[ ...
- [USACO2002][poj1947]Rebuilding Roads(树形dp)
Rebuilding RoadsTime Limit: 1000MS Memory Limit: 30000KTotal Submissions: 8589 Accepted: 3854Descrip ...
- 【树形dp】Rebuilding Roads
[POJ1947]Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 11934 Accep ...
- POJ1947 Rebuilding Roads[树形背包]
Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 11495 Accepted: 5276 ...
- POJ 1947 Rebuilding Roads
树形DP..... Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8188 Accepted: ...
- POJ 1947 Rebuilding Roads 树形DP
Rebuilding Roads Description The cows have reconstructed Farmer John's farm, with its N barns (1 & ...
- BZOJ 1626: [Usaco2007 Dec]Building Roads 修建道路( MST )
计算距离时平方爆了int结果就WA了一次...... ------------------------------------------------------------------------- ...
- 【Luogu1272】重建道路(动态规划)
[Luogu1272]重建道路(动态规划) 题面 题目描述 一场可怕的地震后,人们用N个牲口棚(1≤N≤150,编号1..N)重建了农夫John的牧场.由于人们没有时间建设多余的道路,所以现在从一个牲 ...
- 洛谷 P1272 重建道路 解题报告
P1272 重建道路 题目描述 一场可怕的地震后,人们用\(N\)个牲口棚\((1≤N≤150\),编号\(1..N\))重建了农夫\(John\)的牧场.由于人们没有时间建设多余的道路,所以现在从一 ...
随机推荐
- [打基础]luogu2181对角线——计数原理
啦啦啦我ysw又回来啦!之后大概会准备打acm,暑假尽量复习复习,因为已经快两年没碰oi了,最多也就高三noip前学弟学妹出题讲题,所以从这一篇blog开始大概会有一系列"打基础" ...
- Kylin的特点
Kylin的特点 0.原理 从Hive读取数据,计算引擎可以用MapReduce 或者Spark, 把结果写入Hbase. 下次查询就会很快,也就是所谓的预计算. 1.为什么会有Kylin? hive ...
- BUUCTF | [网鼎杯 2020 朱雀组]phpweb
一道比较简单的题,不过对PHP还是不够熟悉 知识点 1.PHP date函数 PHP date() 函数用于对日期或时间进行格式化. 语法 date(format,timestamp) 参数 描述 f ...
- [C#] (原创)进度等待窗口(附:自定义控件的使用)
一.前言 技术没有先进与落后,只有合适与不合适. 在程序当中,经常有耗时较长的操作,为了给用户更好的体验,就需要给用户一个及时的反馈,这种时候就需要用到进度等待窗口. 实现进度等待窗口的技术有很多,比 ...
- MySQL5.7.26安装及启动报错解决
一.安装依赖包 [root@db01 ~]# yum install -y lrzsz [文件上传/下载] [root@db01 ~]# yum -y install xfsprogs [安装磁盘格式 ...
- 上传报错,ITMS-90167,解决办法
ERROR ITMS-90167 No .app bundles found in the package 报这个错误的原因是上传工具的版本问题或者本地网络问题. 解决办法是使用在线最新的上传工具,推 ...
- 在项目中随手把haseMap改成了currenHaseMap差点被公司给开除了。
前言 在项目中随手把haseMap改成了currenHaseMap差点被公司给开除了. 判断相等 字符串判断相等 String str1 = null; String str2 = "jav ...
- IDEA和eclips工具对比
描述 eclipse idea 在当前类查找方法 ctrl+o ctrl+F12 查找文件 ctrl+shift+N 大小写转换 ctrl+shift+X ctrl+shift+Y ctrl ...
- 手写一个简单的starter组件
spring-boot中有很多第三方包,都封装成starter组件,在maven中引用后,启动springBoot项目时会自动装配到spring ioc容器中. 思考: 为什么我们springBoot ...
- [leetcode]692. Top K Frequent Words频率最高的前K个单词
这个题的排序是用的PriorityQueue实现自动排列,优先队列用的是堆排序,堆排序请看:http://www.cnblogs.com/stAr-1/p/7569706.html 自定义了优先队列的 ...