分层最短路

分层最短路问题是在最短路基础上增加条件,允许将k条边权值设为0。通过构建多层图并利用动态规划或暴力建图方法求解。动态规划状态转移方程描述了在不同机会下节点间最短路径的变化。AC代码可用于实际问题解决。
摘要由CSDN通过智能技术生成

分层最短路

介绍

分层图最短路在最短路的基础上,增加了一个条件:可将 k 条边的权值变为 0.

分析

这种问题我们可以想到一种做法:

img

如图,我们构建一个多层的图,其中每一层都是和题目中给的图相同.(图中假设k==1)上面的层表示不将任何边的权值变为0,而下面的这一层表示使用了这个机会后的状态.

也就是0号节点可以不使用机会,转移到2号节点,也可以使用机会转移到7号(其实就是二号的镜像节点).最后我们只需要看0到4或者9的路径谁更短即可(实际上只要是正权图,一般都是下面的节点路径短)

基本原理懂了之后,就是怎么实现的问题.

暴力建图

根据刚才的讨论,我们不难发现,只要把分层图构建出来,就能直接跑dijkstra算法,只要将每个点都拆成(k+1)个,然后将层与层之间的联系构建起来,起点是0号,终点是n*(k+1)-1 这种算法是可行的,写起来也更简洁,而且不用修改最短路的算法,只是有一些暴力.

动态规划

参考博客

我们用dp的角度去思考这个问题.我们令dp[i][j]表示从0号到i号节点,经由j次免费转移所耗费的成本 .

设会有 K 次免费机会,则 dis的状态转移方程为:

dis[i][j]=min(dis[father][j−1],dis[father][j]+w)

其中, father 表示节点i的父亲节点(此处表述有歧义,此转移方程发生在对边的松弛过程中,当前边是father -> i,而使用j次机会i号节点可以由father[j]father[j-1]转移).当 j−1>=k时,dis[father][j]=INF

AC代码

洛谷P4568 飞行路线

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <list>
#include <cstring>
#include <map>
#include <limits>
#include <cmath>
#define IN freopen("in.txt","r",stdin);
using namespace std;
typedef long long int ll;
const int maxn = 1e5+10;
const int INF = 0x3f3f3f3f;

struct State
{
                     // 优先队列的结点结构体
    int v, w, cnt; // cnt 表示已经使用多少次免费通行权限
    State() {
   }
    State(int v, int w
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值