[洛谷-P1272] 重建道路(树形背包DP)
创始人
2024-06-01 00:17:00
0

[洛谷-P1272] 重建道路(树形背包DP)

  • 一、题目
  • 重建道路
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 提示
      • 样例解释
      • 限制与约定
  • 二、思路
    • 1、状态表示
    • 2、转移方程
    • 3、循环设计
    • 4、初末状态
  • 三、代码

一、题目

重建道路

题目描述

一场可怕的地震后,人们用 NNN 个牲口棚(编号 1∼N1\sim N1∼N)重建了农夫 John 的牧场。由于人们没有时间建设多余的道路,所以现在从一个牲口棚到另一个牲口棚的道路是惟一的。因此,牧场运输系统可以被构建成一棵树。

John 想要知道另一次地震会造成多严重的破坏。有些道路一旦被毁坏,就会使一棵含有 PPP 个牲口棚的子树和剩余的牲口棚分离,John 想知道这些道路的最小数目。

输入格式

第一行两个整数,NNN 和 PPP。

第二行到第 nnn 行,每行两个整数 III 和 JJJ,表示节点 III 是节点 JJJ 的父节点。牧场运输系统可以被构建成一棵以 1 号节点为根的树

输出格式

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

样例 #1

样例输入 #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−41-41−4 和 1−51-51−5 被破坏,含有节点(1,2,3,6,7,81,2,3,6,7,81,2,3,6,7,8)的子树将被分离出来。

限制与约定

1≤N≤1501\le N\le 1501≤N≤150,1≤P≤N1\le P\le N1≤P≤N,保证给出的是一棵树。

二、思路

这道题简单的来说就是:
给出一棵含有 n 个节点的有根树,我们现在希望通过删除一些边,让他有一棵有 m 个节点的新树,求删除的最少边的数量。

我们需要注意的有一下几点:
第一,我们选择的点必须构成一棵树,即如果我们选择了一个点,那么就必须选择这个点的父节点。 从这里我们就能够发现这道题其实是一道树形背包DP的问题。

剩下的注意点将在DP的分析中给出。

1、状态表示

f[u][j]f[u][j]f[u][j]表示在以uuu为根节点的树中选择jjj个点,删除的最小边的数量。

2、转移方程

f[u][siz(u)][j]=min(f[u][siz(u)][j],f[u][siz(u)−1][j−k]+f[son][siz(son)][k]−2)f[u][siz(u)][j]=min(f[u][siz(u)][j], f[u][siz(u)-1][j-k]+f[son][siz(son)][k]-2)f[u][siz(u)][j]=min(f[u][siz(u)][j],f[u][siz(u)−1][j−k]+f[son][siz(son)][k]−2)

这里的sonsonson指的是uuu的子节点。siz(u)siz(u)siz(u)指的是uuu的子树个数。siz(son)siz(son)siz(son)指的是其子树的子树个树。那么上述的转移方程可以描述为:

在以uuu为根的子树中选jjj个节点的最小代价等于在前siz(u)−1siz(u)-1siz(u)−1个子树中选j−kj-kj−k个,在第siz(u)siz(u)siz(u)个子树sonsonson中选kkk个的最小代价。

我们为什么要减222呢?

我们在初始化的时候,我们是切除了和子节点之间相连的边,同时也切除了和父节点相连的边。
在这里插入图片描述
A是B的父节点,所以在算红色的联通块的时候,我们删除了一次A和B之间的边,B又是A的子节点,所以在算紫色连通块的时候,我们又删除了一次A和B之间的边。但实际上我们是需要在A和B之间连接一条边的。也就是说我们不应该删除这条边。我们的f[i][j]f[i][j]f[i][j]记录的是删除掉的边。所以我们应该-2。

这里我们还需要注意一个关键点:根据刚刚的分析,我们想要选择子树中的点就必须选择这个点所对的根节点。即如果我们总共想选择jjj个点,那么我们在子树中至多选j−1j-1j−1个。这个即我们kkk的范围。

而上述三维的DP是比较容易爆空间的,所以可以优化为两维:
f[u][j]=min(f[u][j],f[u][j−k]+f[son][k]−2)f[u][j]=min(f[u][j], f[u][j-k]+f[son][k]-2)f[u][j]=min(f[u][j],f[u][j−k]+f[son][k]−2)

3、循环设计

最外层肯定是去遍历树的节点,利用子节点去更新父节点,所以我们最外层的循环其实就是DFS。

那么第二层循环就是我们的选择的点的个数jjj。但是由于我们优化掉了一维,所以我们需要倒序枚举。

第三层即去枚举在子树sonsonson中选择的个数。

4、初末状态

f[u][1]f[u][1]f[u][1]表示的是在以uuu为根的树中保留一个点所需要的最小代价,即保留uuu点本身。
那么我们只需要剪掉和uuu直接相连的子节点即可剪去整棵子树,但是不要忘记和节点uuu相连的父节点也要减去!

即f[u][1]=siz(u)+1f[u][1]=siz(u) + 1f[u][1]=siz(u)+1,其余初始化正无穷INFINFINF即可。

但是这里有一个特殊情况,如果我们的uuu是整棵树的祖宗节点rootrootroot。而祖宗节点是没有父节点的,所以我们不需要减去那个和父节点相连的边,此时我们只需要初始化为:f[root][1]=siz(root)f[root][1]=siz(root)f[root][1]=siz(root)。这是这道题的另外一个坑点。

末状态是f[root][p]f[root][p]f[root][p],这个想法对吗?
显然是不对的。因为题目中只说保留ppp个,并没有说保留的是以祖宗节点rootrootroot为根。所以我们需要去枚举所有的f[i][p]f[i][p]f[i][p],找出一个最小值。

三、代码

#include
#include
#include
#include
#define endl '\n'
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair pii;
const int N = 300 + 10;
int f[N][N];
int siz[N];
int root = 0;
vectoredge[N];
int n, m;
void dp(int u, int M)
{f[u][1] = edge[u].size() + (u != root);for(int i = 0; i < edge[u].size(); i ++ ){int son = edge[u][i];dp(son, M);for(int j = M; j >= 1; j -- )for(int q = 0; q <= (j - 1); q ++ )f[u][j] = min(f[u][j - q] + f[son][q] - 2, f[u][j]);}
}
void solve()
{cin >> n >> m;memset(f, INF, sizeof f);for(int i = 0; i < n - 1; i ++ ){int a, b;cin >> a >> b;if(root == b || root == 0)root = a;edge[a].push_back(b);}dp(root, m);int ans = f[root][m];for(int i = 1; i <= n; i ++ ){if(f[i][m] < ans)ans = f[i][m];}cout << ans << endl;
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);solve();
}

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...