【图论】【最短路】斯坦纳树

本文详细介绍了斯坦纳树问题,包括定义、应用背景及其求解算法。通过动态规划方法求解最小斯坦纳树问题,利用松弛操作进行状态更新,最终找到连接指定顶点集合的最短路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

斯坦纳树

  • 给定n个点,试求连接此n个点,总长最短的直线段连接系统,并且任意两点都可由系统中的直线段组成的折线连接起来。

  • 模板题:无向连通图,可能自环和重边,给定k个关键点,求一个子图使得边权和最小。

  • 分析

    • 子图一定是树,否则一定可以去环使得边权和变小。这棵树就是最小斯坦纳树。
    • d p ( i , S ) dp(i,S) dp(i,S) 表示 i i i 为根,包含点集 S S S 中所有点的最小权值和
    • T T T S S S 的子集,则 d p ( i , S ) dp(i,S) dp(i,S) d p ( i , T ) + d p ( i , S − T ) dp(i,T)+dp(i,S-T) dp(i,T)+dp(i,ST) 转移而来。
    • 松弛操作,对于 i i i 的相邻节点 j j j f ( i , S ) = m i n ( f ( i , S ) , f ( j , S ) + w ( j , i ) ) f(i,S)=min(f(i,S),f(j,S)+w(j,i)) f(i,S)=min(f(i,S),f(j,S)+w(j,i))
  • 整体步骤

    • d p dp dp 初始化为 0 x 3 f 3 f 3 f 3 f 0x3f3f3f3f 0x3f3f3f3f
    • 枚举给定点的子集 S S S
      • 对于 S S S 枚举子集 T T T ,更新每个节点的 d p dp dp
      • 如果权值和被更新,说明这个点可行,加入 s p f a spfa spfa 的队列
      • 进行 s p f a spfa spfa 更新队列中点的相邻点的答案
    • 答案是给定点中的任意点 i i i d p dp dp
for (int i = 0; i < k; i++)
{
	read(p[i]);
	dp[p[i]][1 << i] = 0;
}
int up = (1 << k) - 1;
for (int s1 = 0; s1 <= up; s1++) //枚举给定点的子集递推
{
	for (int i = 1; i <= n; i++)
	{
		for (int s2 = s1 & s1 - 1; s2; s2 = s2 - 1 & s1)			//枚举当前点集的子集
			dp[i][s1] = min(dp[i][s1], dp[i][s2] + dp[i][s1 ^ s2]); //dp(i,S)<-dp(i,T)+dp(i,S_T)
		if (dp[i][s1] < INF)
		{
			q.push(i);
			vst[i] = true;
		}
	}
	spfa(s1); 
}
//spfa里的松弛操作:
// if (dp[v][S] > dp[u][S] + w)
// {
// 	dp[v][S] = dp[u][S] + w;
// 	if (!vst[v]) //如果不在队列里就加入
// 		q.push(v), vst[v] = true;
// }

模板题传送门:洛谷P6192 【模板】最小斯坦纳树
例题传送门:洛谷P4294 [WC2008]游览计划

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值