最短路,即第1短路有很多种求法,SPFA,Dijkstra等,但第k短路怎么求呢?其实也是基于Dijkstra;因为Dijkstra用的是堆优化,这样保证每次弹出来的都是最小值,只是求最短路只是弹出一次就返回了,我们可以用Dijkstra弹出k个距离后再返回,这样根据弹出的先后顺序能够求出1~k短路

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 5e5 + 100;
const int MAXM = 3e3 + 10; inline int read() {
int x = 0, ff = 1; char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') ff = -1;
ch = getchar();
}
while(isdigit(ch)) {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * ff;
} inline void write(ll x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
} int n, m, k, v;
ll ans, dist[110];
int lin[MAXN], tot = 0;
struct edge {
int y, v, next;
}e[MAXN]; inline void add(int xx, int yy, int vv) {
e[++tot].y = yy;
e[tot].v = vv;
e[tot].next = lin[xx];
lin[xx] = tot;
} void Dijkstra() {
priority_queue < pair < int , int > > q;
q.push(make_pair(0, 1));
while(!q.empty()) {
int x = q.top().second;
int d = -q.top().first;
q.pop();
if(x == n) {
dist[++v] = d;
if(v == k + 1) return ;
}
for(int i = lin[x], y; i; i = e[i].next) {
y = e[i].y;
ans = d + e[i].v;
q.push(make_pair(-ans, y));
}
}
} int main() {
memset(dist, -1, sizeof(dist));
n = read(); m = read(); k = read();
for(int i = 1; i <= m; ++i) {
int x,y,v;
x = read(); y = read(); v = read();
add(x, y, v);
}
Dijkstra();
for(int i = 1; i <= k; ++i) {
write(dist[i]);
putchar('\n');
}
return 0;
}

emmmmm, 还有一种更高级的算法, 先来回顾优先队列的BFS, 不断从堆中取出“当前代价最小” 的状态进行拓展。每个状态第一次从堆中取出时, 就得到了从初态到该状态的最小代价。然而, 一个状态当前最小, 不代表从该状态到目标状态代价就最小,但是优先队列BFS会先选择这个分支, 导致搜索量增大;

所以, 我们能够想到, 设计一个函数, 计算从该状态到目标状态的代价的估计值, 仍然维护一个堆,把当前价值 + 估计价值最小作为拓展;估价函数原则是估价值 <- 实际值(不再证明。。。)

在求第k短路时, 我们把最短路作为估价, 保证估价 <= 实际, 还能顺应实际的变化趋势

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 5e5 + 100;
const int MAXM = 3e3 + 10; template < typename T > inline void read(T &x) {
x = 0; T ff = 1, ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') ff = -1;
ch = getchar();
}
while(isdigit(ch)) {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
x *= ff;
} template < typename T > inline void write(T x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
} int n, m, s, t, k;
int f[MAXN], vis[MAXN];
int lin[MAXN], tot = 0, linc[MAXN], totc = 0;
struct edge {
int y, v, next;
}a[MAXN], e[MAXN]; struct node {
int pos, f, dis;
bool operator < (node a) const {
return a.f + a.dis < f + dis;
}
}; inline void add(int xx, int yy, int vv) {
a[++tot].y = yy;
a[tot].v = vv;
a[tot].next = lin[xx];
lin[xx] = tot;
} inline void addc(int xx, int yy, int vv) {
e[++totc].y = yy;
e[totc].v = vv;
e[totc].next = linc[xx];
linc[xx] = totc;
} void SPFA() {
queue < int > q;
memset(f, 0x3f, sizeof(f));
memset(vis, false, sizeof(vis));
q.push(t);
f[t] = 0;
vis[t] = true;
while(!q.empty()) {
int x = q.front(); q.pop();
vis[x] = false;
for(int i = lin[x], y; i; i = a[i].next) {
if(f[y = a[i].y] > f[x] + a[i].v) {
f[y] = f[x] + a[i].v;
if(!vis[y]) {
vis[y] = true;
q.push(y);
}
}
}
}
} int astar() {
priority_queue < node > q;
if(f[s] == INF) return -1;
int ts[MAXN];
node tmp, h;
h.pos = s; h.f = 0; h.dis = 0;
q.push(h);
while(!q.empty()) {
node x = q.top(); q.pop();
ts[x.pos]++;
if(ts[x.pos] == k && x.pos == t) return x.dis;
if(ts[x.pos] > k) continue;
for(int i = linc[x.pos]; i; i = e[i].next) {
tmp.pos = e[i].y;
tmp.f = f[e[i].y];
tmp.dis = x.dis + e[i].v;
q.push(tmp);
}
}
return -1;
} int main() {
read(n); read(m);
for(int i = 1; i <= m; ++i) {
int u, v, w;
read(u); read(v); read(w);
add(v, u, w);
addc(u, v, w);
}
read(s); read(t); read(k);
if(s == t) ++k;
SPFA();
write(astar());
return 0;
}

第k短路(Dijkstra & A*)的更多相关文章

  1. POJ 2449 第k短路 Dijkstra+A*

    这道题我拖了半年,,,终于写出来了 思路: 先反向建边 从终点做一次最短路 ->这是估价函数h(x) 再正常建边,从起点搜一遍 (priority_queue(h(x)+g(x))) g(x)是 ...

  2. poj 2449 Remmarguts' Date(第K短路问题 Dijkstra+A*)

    http://poj.org/problem?id=2449 Remmarguts' Date Time Limit: 4000MS   Memory Limit: 65536K Total Subm ...

  3. Bzoj 1975: [Sdoi2010]魔法猪学院 dijkstra,堆,A*,K短路

    1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1357  Solved: 446[Submit][Statu ...

  4. Bzoj 1598: [Usaco2008 Mar]牛跑步 dijkstra,堆,K短路,A*

    1598: [Usaco2008 Mar]牛跑步 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 427  Solved: 246[Submit][St ...

  5. hdu 2544 最短路 Dijkstra

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 题目分析:比较简单的最短路算法应用.题目告知起点与终点的位置,以及各路口之间路径到达所需的时间, ...

  6. K短路

    K短路 用dijsktra+A*启发式搜索当点v第K次出堆的时候,这时候求得的路径是k短路.A*算法有一个启发式函数f(p)=g(p)+h(p), 即评估函数=当前值+当前位置到终点的最短距离g(p) ...

  7. 【转】K短路

    K短路 用dijsktra+A*启发式搜索 当点v第K次出堆的时候,这时候求得的路径是k短路.A*算法有一个启发式函数f(p)=g(p)+h(p), 即评估函数=当前值+当前位置到终点的最短距离g(p ...

  8. POJ 2449 求第K短路

    第一道第K短路的题目 QAQ 拿裸的DIJKSTRA + 不断扩展的A* 给2000MS过了 题意:大意是 有N个station 要求从s点到t点 的第k短路 (不过我看题意说的好像是从t到s 可能是 ...

  9. 算法学习笔记(三) 最短路 Dijkstra 和 Floyd 算法

    图论中一个经典问题就是求最短路.最为基础和最为经典的算法莫过于 Dijkstra 和 Floyd 算法,一个是贪心算法,一个是动态规划.这也是算法中的两大经典代表.用一个简单图在纸上一步一步演算,也是 ...

随机推荐

  1. PHP中的MySQLi扩展学习(六)MySQLI_result对象操作

    在之前的文章中,我们就已经接触过 MYSQLI_result 相关的内容.它的作用其实就是一个查询的结果集.不过在 PDO 中,一般直接通过 query() 或者 PDOStatement 对象进行查 ...

  2. appium和selenium不同与相同之处

    原文来自: https://www.cnblogs.com/zhengshuheng/p/6370398.html selenium是web端的自动化,appium是app端的自动化,它继承了webd ...

  3. django 安装redis及session使用redis存储

    环境:centos 7.4 第一:安装redis 下载redis并安装: wget http://download.redis.io/releases/redis-5.0.5.tar.gz yum - ...

  4. maven项目环境变量配置及创建(一)

    Maven是基于JAVA平台的一款编译.测试.打包部署及运行的构建工具 1:首先需要下载安装JDK 2:安装Eclipse 3:下载maven包(https://maven.apache.org/do ...

  5. AVS 通信模块之AVSConnectionManager

    AVSConnectionManager 类为客户端无缝地管理与AVS的连接 功能简介 失败时连接重试 允许后续重新连接 ping管理 AVS服务器断开时周期重连服务器 允许客户端完全启用或禁用连接管 ...

  6. 我在学习Blazor当中踩的巨坑!Blazor WebAssembly调试

    最近嘛,看看Blazor已经蛮成熟的.顺便想在自家的框架里使用这个东西,毕竟我还是很念旧的,而且Blazor的技术栈也不麻烦.然后呢,在调试这一关我可是踩了大坑. 我的VS是2019,很早以前装的.然 ...

  7. 鸿蒙内核源码分析(内存主奴篇) | 皇上和奴才如何相处 | 百篇博客分析OpenHarmony源码 | v10.04

    百篇博客系列篇.本篇为: v10.xx 鸿蒙内核源码分析(内存主奴篇) | 皇上和奴才如何相处 | 51.c.h .o 前因后果相关篇为: v08.xx 鸿蒙内核源码分析(总目录) | 百万汉字注解 ...

  8. 一、Ansible基础之入门篇

    目录 1. Ansible基础 1.1 介绍 1.2 工作原理 1.3 如何安装 1.3.1 先决条件 1.3.2 安装Ansible 1.4 管理节点与被管理节点建立SSH信任关系 1.5 快速入门 ...

  9. 【vue】使用 Video.js 播放视频

    目录 安装 引入 使用 参考文档 环境: vue 2.0+ element ui (这里的代码用了elmentui的按钮样式,可以不用elment ui的样式) 安装 在项目中安装 video.js. ...

  10. apiserver源码分析——处理请求

    前言 上一篇说道k8s-apiserver如何启动,本篇则介绍apiserver启动后,接收到客户端请求的处理流程.如下图所示 认证与授权一般系统都会使用到,认证是鉴别访问apiserver的请求方是 ...