【洛谷P4201】设计路线【树形dp】

动态规划之树形DP 本文主要讨论动态规划中的一种常见应用——树形DP。树形DP通常应用于树状结构的问题中,通过从叶子节点到根节点的动态规划过程,计算出每个节点的状态值,并最终得出问题的解。文章将介绍树形DP的基本思想、常用解法和优化技巧,并给出实例说明。通过本文的学习,读者将对树形DP有一个更深入的理解,能够更好地应用于实际问题解决中。 阅读详情

题目大意:

题目链接:https://www.luogu.org/problemnew/show/P4201
在一个 n n n个点 m m m条边的森林中选择若干路径,同时必须保证每个点最多在一条被选路径上。求所有点到点1的未选路径之和的最小值以及方案数。


思路:

思路来自 S o o k e Sooke Sooke大佬 https://www.luogu.org/blog/Sooke/solution-p4201
显然这个森林为一棵树的时候才能满足所有点都可以到达点1。
所以若 m ≠ n − 1 m≠n-1 m̸​=n−1的话直接输出两个 − 1 -1 −1即可。
剩下的都是一棵树的情况。


先考虑如何求第一问的最小值。
因为一个点为了满足最多在一条被选路径上的要求,所以最多有2条与这个点相连的边被选择。三种情况如下图:
在这里插入图片描述
这三种情况就分别为没有与这个点相邻的边,有1个和有2个。
设 f [ x ] [ i ] f[x][i] f[x][i]表示在以 x x x为根的子树内,有不多于 i ( 0 ≤ x ≤ 2 ) i(0\leq x\leq 2) i(0≤x≤2)条选择的边与 x x x相邻的未选路径之和的最小值。那么先分开成3种情况讨论,然后再取一个 m i n min min即可。
{ f [ x ] [ 2 ] = m i n ( m a x ( f [ x ] [ 2 ] , f [ y ] [ 2 ] + 1 ) , m a x ( f [ x ] [ 1 ] , f [ y ] [ 1 ] ) ) f [ x ] [ 1 ] = m i n ( m a x ( f [ x ] [ 1 ] , f [ y ] [ 2 ] + 1 ) , m a x ( f [ x ] [ 0 ] , f [ y ] [ 1 ] ) ) f [ x ] [ 0 ] = m a x ( f [ x ] [ 0 ] , f [ y ] [ 2 ] + 1 ) \left\{\begin{matrix}f[x][2]=min(max(f[x][2],f[y][2]+1),max(f[x][1],f[y][1]))\\ f[x][1]=min(max(f[x][1],f[y][2]+1),max(f[x][0],f[y][1]))\\ f[x][0]=max(f[x][0],f[y][2]+1)\end{matrix}\right. ⎩⎨⎧​f[x][2]=min(max(f[x][2],f[y][2]+1),max(f[x][1],f[y][1]))f[x][1]=min(max(f[x][1],f[y][2]+1),max(f[x][0],f[y][1]))f[x][0]=max(f[x][0],f[y][2]+1)​
主要是讨论当有 i i i条边与根相邻的情况下子节点有多少条边相邻的限制。
当 i = 0 i=0 i=0时,子节点有多少边相邻都没关系,那就取尽量小的。
当 i = 1 i=1 i=1时,要分类是否与这个子节点相连的边被选择,若被选择这个子节点就只能有1条边连出去,否则依然取最小
当 i = 2 i=2 i=2时和 i = 1 i=1 i=1时基本一样,只不过会有两个子节点需要相邻。
因为我们设的是“不多于 i ( 0 ≤ x ≤ 2 ) i(0\leq x\leq 2) i(0≤x≤2)条选择的边”,所以还要有
{ f [ x ] [ 1 ] = m i n ( f [ x ] [ 1 ] , f [ x ] [ 0 ] ) f [ x ] [ 2 ] = m i n ( f [ x ] [ 2 ] , f [ x ] [ 1 ] ) \left\{\begin{matrix}f[x][1]=min(f[x][1],f[x][0])\\ f[x][2]=min(f[x][2],f[x][1])\end{matrix}\right. {f[x][1]=min(f[x][1],f[x][0])f[x][2]=min(f[x][2],f[x][1])​
这样第一问的答案就是 f [ 1 ] [ 2 ] f[1][2] f[1][2]了。


第二问要求的是方案数。
设 g [ x ] [ j ] [ i ] g[x][j][i] g[x][j][i]表示在以 x x x为根的子树内,子节点的不便利值都不超过 j j j,有不多于 i ( 0 ≤ x ≤ 2 ) i(0\leq x\leq 2) i(0≤x≤2)条选择的边与 x x x相邻的方案数。
可以证明(但是显然我不会 q w q qwq qwq)第一问的答案必然小于等于 log ⁡ 3 n \log_3n log3​n,所以第2维其实是很小的,可以保证空间。
依然分三种情况讨论
{ g [ x ] [ j ] [ 2 ] = g [ x ] [ j ] [ 2 ] × g [ y ] [ j − 1 ] [ 2 ] + g [ x ] [ j ] [ 1 ] × g [ y ] [ j ] [ 1 ] g [ x ] [ j ] [ 1 ] = g [ x ] [ j ] [ 1 ] × g [ y ] [ j − 1 ] [ 2 ] + g [ x ] [ j ] [ 0 ] × g [ y ] [ j ] [ 1 ] g [ x ] [ j ] [ 0 ] = g [ x ] [ j ] [ 0 ] × g [ y ] [ j − 1 ] [ 2 ] \left\{\begin{matrix}g[x][j][2]=g[x][j][2]\times g[y][j-1][2]+g[x][j][1]\times g[y][j][1]\\ g[x][j][1]=g[x][j][1]\times g[y][j-1][2]+g[x][j][0]\times g[y][j][1]\\ g[x][j][0]=g[x][j][0]\times g[y][j-1][2]\end{matrix}\right. ⎩⎨⎧​g[x][j][2]=g[x][j][2]×g[y][j−1][2]+g[x][j][1]×g[y][j][1]g[x][j][1]=g[x][j][1]×g[y][j−1][2]+g[x][j][0]×g[y][j][1]g[x][j][0]=g[x][j][0]×g[y][j−1][2]​
当 i = 0 i=0 i=0时,方案数显然就是每一个子树都连两条边的方案数之积。
当 i = 1 i=1 i=1或 i = 2 i=2 i=2时,方案数就是其中1,2条边与子节点连接,其他全部为子节点的方案数之积。
其实 g g g的方程和 f f f的方程及其相似。
还是那样,最终取一个 m i n min min
{ g [ x ] [ i ] [ 1 ] = g [ x ] [ i ] [ 1 ] + g [ x ] [ i ] [ 0 ] g [ x ] [ i ] [ 2 ] = g [ x ] [ i ] [ 2 ] + g [ x ] [ i ] [ 1 ] \left\{\begin{matrix}g[x][i][1]=g[x][i][1]+g[x][i][0]\\ g[x][i][2]=g[x][i][2]+g[x][i][1]\end{matrix}\right. {g[x][i][1]=g[x][i][1]+g[x][i][0]g[x][i][2]=g[x][i][2]+g[x][i][1]​
最终第二问答案就是 g [ 1 ] [ f [ 1 ] [ 2 ] ] [ 2 ] g[1][f[1][2]][2] g[1][f[1][2]][2]。
总时间复杂度 O ( n ) O(n) O(n)


代码:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;

const int N=100010;
const ll Inf=1e17;
int n,m,tot,head[N];
ll f[N][3],g[N][15][3],MOD;

struct edge
{
	int next,to;
}e[N*2];

void add(int from,int to)
{
	e[++tot].to=to;
	e[tot].next=head[from];
	head[from]=tot;
}

void dp1(int x,int fa)
{
	f[x][0]=1; f[x][1]=Inf; f[x][2]=Inf;
	for (int i=head[x];~i;i=e[i].next)
	{
		int y=e[i].to;
		if (y!=fa)
		{
			dp1(y,x);
			f[x][2]=min(max(f[x][2],f[y][2]+1),max(f[x][1],f[y][1]));
			f[x][1]=min(max(f[x][1],f[y][2]+1),max(f[x][0],f[y][1]));
			f[x][0]=max(f[x][0],f[y][2]+1);
		}
	}
	f[x][1]=min(f[x][1],f[x][0]);
	f[x][2]=min(f[x][2],f[x][1]);
}

void dp2(int x,int fa)
{
	for (int i=1;i<=f[1][2];i++)
		g[x][i][0]=1;
	for (int i=head[x];~i;i=e[i].next)
	{
		int y=e[i].to;
		if (y!=fa)
		{
			dp2(y,x);
			for (int j=1;j<=f[1][2];j++)
			{
				g[x][j][2]=(g[x][j][2]*g[y][j-1][2]+g[x][j][1]*g[y][j][1])%MOD;
				g[x][j][1]=(g[x][j][1]*g[y][j-1][2]+g[x][j][0]*g[y][j][1])%MOD;
				g[x][j][0]=(g[x][j][0]*g[y][j-1][2])%MOD;
			}
		}
	}
	for (int i=1;i<=f[1][2];i++)
	{
		g[x][i][1]=(g[x][i][1]+g[x][i][0])%MOD;
		g[x][i][2]=(g[x][i][2]+g[x][i][1])%MOD;
	}
}

int main()
{
	memset(head,-1,sizeof(head));
	scanf("%d%d%lld",&n,&m,&MOD);
	if (m!=n-1) return !printf("-1\n-1");
	for (int i=1,x,y;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		add(x,y); add(y,x);
	}
	dp1(1,0); 
	dp2(1,0);
	printf("%lld\n%lld",f[1][2]-1,g[1][f[1][2]][2]);
	return 0;
}
【机器视觉】Halcon 最新版本安装教程(HALCON 24.11.1.1 Progress-Steady) 注:如果使用评估版本,下载前先了解最新评估授权密钥所支持的版本。。近几年不同版本安装过程类似,均可参考本教程。 阅读详情

相关推荐

Oracle PLM Agile936 单点登录配置方式

Oracle PLM Agile936 单点登录配置方式

Jay的个人博客 824

洛谷树形DP(基础)

洛谷树形DP前22题(基础) xzy的树形dp题单 - 题单 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) P1122 最大子树和 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意:对一棵树进行删边,判断删完边之后连通块最大权值之和是多少? 定义f[cur]f[cur]f[cur]为以curcurcur为根的子树权值之和最大值 初始值f[cur]=w[cur]f[cur] = w[cur]f[cur]=w[cur] 如果他的其中一棵子树大于0,则选择这棵子树。 f

weixin_45360119的博客 771

自由曲面与衍射光学元件DOE:从基础理论到工业应用的全景解析

本文全景解析了自由曲面与衍射光学元件的核心理论与工业应用。文章深入探讨了自由曲面在非对称光学设计中的灵活性及其数学描述与制造挑战,并阐述了衍射光学元件通过微纳结构进行波前相位调制的原理与多样化功能。两者与经典光学互补融合,共同构成了高端成像、智能照明、激光加工及AR/VR等前沿领域的底层技术支柱。

devops8pract的博客 390

树形DP整理

树形DP整理 (此文章部分概念引自《信息学奥赛一本通·提高篇》,特此声明!) 文章目录树形DP整理基本概念经典问题例题由根分成左右子树两部分的情况(普通树可通过多叉转二叉转为二叉树)【例1】二叉苹果树 luogu2015【例2】选课 luogu2015(多叉转二叉)背包类树形DP【例3】 选课选课 luogu2015(背包)求树的最长链问题【例4】longest mzoj1264求树的最大独立集...

竹摇清影照幽窗 701

unity 在透明物体上投射阴影

unity版本:2019.4.16 创建一个shader,代码如下: Shader "ChuckLee/ARShadow" { Properties { _ShadowColor("Shadow Color", Color) = (0.1, 0.1, 0.1, 0.53) } SubShader { Tags{ "RenderType" = "Transparent" "Queue" = "Geometry+1" } Blend SrcAlpha OneMinusSrcAlph

Abel02的博客 2953

0018-量化第五天:QMT—日内回转回测注释

日内做T算法框架

m0_68750710的博客 4144

【树形DP】树形DP入门详解+例题剖析

树形DP 树形DP准确的说是一种DP的思想,将DP建立在树状结构的基础上。整体的思路大致就是用树形的结构存储数据。 要学树形DP之前肯定是要先学会树和图的呀,至少先学会链式前向星,不会的话可以看一下我之前写的博客 链接:【图论】图,实现图(三种方式),二分图 详解 树形DP的关键和实现方法是dfsdfsdfs。 先找到树根,从树根开始运用 dfsdfsdfs 递归,跟dfsdfsdfs一样先初始化...

繁凡さん的博客 1万+

线性代数知识点整理

线性代数基础知识点摘要整理

cuguanren的博客 3万+

动态规划——树形dp

树形 DP,即在树上进行的 DP。由于树固有的递归性质,树形 DP 一般都是递归进行的。在树上设计动态规划算法时,一般就以节点从深到浅(子树从小到大)的顺序作为DP的“阶段”,DP的状态表示中,第一维通常是节点编号(代表以该节点为根的子树)。自底向上dfs,属于树的后序遍历

qq_57150526的博客 4294

BIOS/UEFI完全指南:从开机自检到超频魔改的底层硬件控制

计算机启动过程始于固件层,其核心是负责硬件初始化与引导的系统软件。传统BIOS基于16位实模式,寻址能力有限,而现代UEFI采用保护模式,支持图形界面与安全启动,实现了从概念到架构的革新。这一演进带来了显著的技术价值:更快的启动速度、更强的安全性以及对大容量存储设备的原生支持。在工程实践中,无论是解决“虚拟化技术禁用”问题、调整内存XMP配置以提升性能,还是为老主板“魔改”添加NVMe支持,都需要深入理解并操作BIOS/UEFI设置。掌握这些底层交互能力,是进行硬件调试、系统优化与故障排查的关键,也是连接抽

weixin_34236869的博客 456

基金估值核算系统三国杀:恒生 VS 赢时胜 VS 融选!

本文对比分析了恒生电子、赢时胜和融选科技三家金融科技公司的基金估值系统。恒生电子作为行业龙头,在公募基金领域占据较大份额,其新一代估值系统6.0采用微服务架构,自动化程度高;赢时胜在中型公募和券商资管领域优势明显,其V5.5系统在信创适配和复杂产品处理方面表现突出;融选科技作为新兴厂商,提供轻量化解决方案,适合中小型机构。文章从市场格局、系统定位、技术架构、成本构成和用户反馈五个维度进行深入比较,为金融机构选型提供参考。当前估值系统市场呈现"三国鼎立"格局,各具特色,选型需结合机构规模、

magbox520的博客 825

【题解】洛谷 P4201 [NOI2008] 设计路线 [树形 DP]

我爱三段式。

Isaac Regulus的博客 953

CE电流法测试中的dBμV负值解析

传导发射(CE)电流法测试中出现的dBμV负值现象表明被测设备干扰电平低于1μV参考基准。这源于对数计算特性(小于1μV的电压转换后为负值)、设备优良的EMC设计(如滤波效果显著)及测试环境的影响(LISN隔离、屏蔽室低噪声)。负值虽不代表实际负电压,但反映干扰水平优于标准限值,为系统集成预留电磁裕度。工程应用中需结合设备灵敏度、环境背景噪声等因素综合分析,避免误判,这类数据可用于评估EMI设计冗余度。

硬核科技 297

洛谷$P4201\ [NOI2008]$ 设计路线 树形$dp$

正解:树形$dp$ 解题报告: 传送门 先大概港下这题的题意是啥$qwq$ 大概就是给一棵树,然后可以选若干条链把链上的所有边的边权变成$0$,但是这些链不能有交集,问所有点到根的边权最大值的最小值是多少,然后有几种这样的方案 好那我们总算把题目理清了$QAQ$开始讲题$QAQ$ 考虑设$f_{i,j,0/1/2}$表示考虑到第$i$个点了,$i$的子树中的最大边权和=$j$,连了$...

qq_42692055的博客 76

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

洛谷P4201 [NOI2008]设计路线——题解

题目传送门 题目大意: 给定一棵树,你可以在上面指定一些不相交的链,试问从每个节点到根经过的非链边最多的最小值是多少。 思考过程&amp;具体做法: 看别人的题解艰难地写出来的。 首先impossible很好判断,图不联通直接输出就行了。 图联通的话, 我们对于每一个点,在所有向下的路径中选择最长的两条,然后把这两条全部变成铁路。那么假设f(x)为有x节点的树的最大可能答案...

CleverLarry的博客 384

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

【算法笔记】树形DP算法总结&详解

树形DP,又称树状DP,即在树上进行的DP,是DP(动态规划)算法中较为复杂的一种。本文将以例题+算法的形式,详细讲解这种算法。

天生我材必有用,千金散尽还复来。 1万+

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

算法:树形dp(树状dp)

树状dp的基本概念 和 模板题

m0_63997099的博客 3926

树形动态规划详解

本文系统介绍了树形动态规划(Tree DP)的核心原理、经典模型和高级技巧,并提供了C++实现模板。主要内容包括:1)树形DP的基本概念和解题步骤;2)通用框架与状态设计模板;3)三大经典问题实现(最大独立集、最小点覆盖、最小支配集);4)进阶模型(树上背包、树直径、树重心);5)换根DP等高级技巧。通过20+经典问题解析,帮助读者掌握在树形结构上应用动态规划的方法,实现从基础到实战的进阶。

7.15之前尽量一天一更,更新C++,Java的相关代码知识(基础) 1259

深入学习C++:什么是树状DP

树状DP是动态规划在树结构上的应用,利用树的递归特性,通过子树状态推导父节点状态。核心特点包括:依赖树结构、状态与子树相关、无后效性。基本步骤为选根、定义状态、推导转移方程、递归计算。典型应用包括最大独立集、树的直径和最小支配集问题。示例展示了二叉树抢劫问题,通过定义节点选/不选状态,后序遍历计算最优解。时间复杂度O(n),空间复杂度O(h)。

善良的小乔的博客 1413

算法套路十九——树形DP

树形 DP,即在树上进行的 DP。由于树固有的递归性质,这里的DP是指是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法,故虽然带有DP,但一般都是通过来进行。

Pistachiout的学习博客 2258

动态规划入门(七) 树状DP详解

简而言之是dfs里的动态规划,在深搜过程中动态规划最优解,而树就分为枝叶,由根深搜到枝叶末端。树状dp特点(呈树形发散状)是...

这里是阿安的博客 1081

树形DP总结

树形DP总结

ZhuRanCheng的博客 746

动态规划进阶:树形DP深度解析

树形DP是动态规划在树形结构上的应用,通过递归遍历树,在子树上进行动态规划。这类问题通常需要后序遍历(自底向上)来计算每个节点的状态值。:以node为起点的最大路径和全局变量max_sum记录全局最大路径和res[0]:不抢劫当前房屋的最大金额res[1]:抢劫当前房屋的最大金额0: 未被监控1: 有摄像头2: 被监控但无摄像头返回一个元组:(是否是BST, 最小值, 最大值, 节点数)定义状态确定每个节点需要返回什么信息通常返回一个元组或多个值确定递归终止条件空节点返回基础值。

weixin_43680337的博客 635

什么是树形DP?

在树形DP中,我们通过定义状态和状态转移方程,来解决一些与树相关的问题,比如最长路径、最小路径覆盖等等。首先初始化当前节点的大小为1,表示节点本身的大小,然后遍历当前节点的所有孩子节点,并递归地计算它们的子树大小。下面是一个简单的树形DP算法示例,用C++实现,它解决的问题是对于一个有根树,计算树的重心和子树大小。下面是两个 C++ 实现树形 DP 的例子,其中以计算以节点 1 为根节点的树的最长路径为例。,即除了当前节点子树以外的大小,比较出该节点的重心。即为以节点 1 为根节点的树的最长路径。

xmz12300的博客 592

树形 DP 从入门到进阶:普通树形DP、树形背包、换根DP

本文摘要: 树形动态规划(树形DP)是在树结构上进行动态规划的算法,适用于具有层次化关系的问题。文章通过三道经典题目系统讲解了树形DP的三种核心形态: 基础树形DP(选/不选模型):以"没有上司的舞会"为例,展示了如何设计状态表示节点选或不选时的最优解,并通过后序遍历自底向上合并子树信息。 树形背包问题:以"选课"问题为例,演示了如何在树上应用分组背包思想,将有限资源(选课名额)分配给各个子树,通过虚拟根节点将森林转化为树进行处理。 换根DP:简要提及通过改变根节点后快速重新计算答案的技巧。 文章详细分析了

分享 C/C++、Linux、网络的学习历程与实操心得~ 不追求一蹴而就,只坚持日积月累。未来还将拓展更多技术领域,愿与所有热爱技术的伙伴一起,在探索中成长,在坚持中进步! 569

【动态规划】树形DP

树形DP是在树上进行的动态规划,通过DFS后序遍历,定义节点状态并由子节点转移而来,常用于求解树的最大独立集、重心、直径等问题。

zhangmohan123321的博客 1167
上一篇: 【BZOJ1826】【洛谷P4404】缓存交换【贪心】【堆】
下一篇: 随机跳题挑战总结 Part4
stoorz1023
博客等级 码龄9年 101粉丝 595原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值