最短路,即第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. 机器学习——逻辑回归(Logistic Regression)

    1 前言 虽然该机器学习算法名字里面有"回归",但是它其实是个分类算法.取名逻辑回归主要是因为是从线性回归转变而来的. logistic回归,又叫对数几率回归. 2 回归模型 2. ...

  2. Linux系列(2) - 命令提示符

    命令提示符 起始符 [root@localhost ~]# root:当前登录用户 localhost:主机名 ~:当前所在目录(家目录);管理员为 /root ,user用户为 /home/user ...

  3. Redis限流

    在电商开发过程中,我们很多地方需要做限流,有的是从Nginx上面做限流,有的是从代码层面限流等,这里我们就是从代码层面用Redis计数器做限流,这里我们用C#语言来编写,且用特性(过滤器,拦截器)的形 ...

  4. SonarQube安装Java扫描插件

    近段时间在研究sonarqube,成功扫描python项目,但是扫描java项目失败. 在网上查询到,扫描java项目需要安装Java插件. 如下图: 而我在最新的sonarqube中搜索java,没 ...

  5. jmeter旅程第二站:jmeter登录接口测试

    因为上一篇已经讲了jmeter抓包,那么接下来会将讲解jmeter接口测试. 这里以浏览器为例. 从简到繁,那么首先先以比较常见的登录做实例. 目前登录操作有这几种:账户是否存在.账户密码登录.验证码 ...

  6. P3309-[SDOI2014]向量集【线段树,凸壳】

    正题 题目链接:https://www.luogu.com.cn/problem/P3309 题目大意 \(n\)个操作 在序列末尾加入一个向量\((x,y)\) 询问加入的第\(l\sim r\)个 ...

  7. Jmeter压力测试学习7--压测带token的接口

    前言 工作中我们需要压测的接口大部分都是需要先登陆后,带着token的接口(或者带着cookies),我们可以先登陆获取token再关联到下个接口.比如我现在要压测一个修改用户的个人的密码 场景案例 ...

  8. Jmeter 压力测试学习8--断言

    断言成功是不会显示的,失败会有提示. 登录断言 一.添加断言 登录->添加->断言->响应断言 二.执行,查看断言 登录配置的都是正确的用户名跟密码 如果响应断言中内容改为:&quo ...

  9. pycharm中安装扩展包

    在使用Pycharm编写代码时,如果遇到了所需要的扩展包没有的情况时,可以使用以下方法来添加自己需要的扩展包. 1.点击File->settings 2.选择Project Interprete ...

  10. 一个Electron的设计缺陷及应对方案

    当你想实现阻止Electron窗口关闭,并弹出询问对话框,提示用户:"文章尚未保存,是否要关闭窗口"这类业务时,那么你99%会碰到这个BUG: https://github.com ...