第k短路(Dijkstra & A*)
最短路,即第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*)的更多相关文章
- POJ 2449 第k短路 Dijkstra+A*
这道题我拖了半年,,,终于写出来了 思路: 先反向建边 从终点做一次最短路 ->这是估价函数h(x) 再正常建边,从起点搜一遍 (priority_queue(h(x)+g(x))) g(x)是 ...
- poj 2449 Remmarguts' Date(第K短路问题 Dijkstra+A*)
http://poj.org/problem?id=2449 Remmarguts' Date Time Limit: 4000MS Memory Limit: 65536K Total Subm ...
- Bzoj 1975: [Sdoi2010]魔法猪学院 dijkstra,堆,A*,K短路
1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1357 Solved: 446[Submit][Statu ...
- Bzoj 1598: [Usaco2008 Mar]牛跑步 dijkstra,堆,K短路,A*
1598: [Usaco2008 Mar]牛跑步 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 427 Solved: 246[Submit][St ...
- hdu 2544 最短路 Dijkstra
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 题目分析:比较简单的最短路算法应用.题目告知起点与终点的位置,以及各路口之间路径到达所需的时间, ...
- K短路
K短路 用dijsktra+A*启发式搜索当点v第K次出堆的时候,这时候求得的路径是k短路.A*算法有一个启发式函数f(p)=g(p)+h(p), 即评估函数=当前值+当前位置到终点的最短距离g(p) ...
- 【转】K短路
K短路 用dijsktra+A*启发式搜索 当点v第K次出堆的时候,这时候求得的路径是k短路.A*算法有一个启发式函数f(p)=g(p)+h(p), 即评估函数=当前值+当前位置到终点的最短距离g(p ...
- POJ 2449 求第K短路
第一道第K短路的题目 QAQ 拿裸的DIJKSTRA + 不断扩展的A* 给2000MS过了 题意:大意是 有N个station 要求从s点到t点 的第k短路 (不过我看题意说的好像是从t到s 可能是 ...
- 算法学习笔记(三) 最短路 Dijkstra 和 Floyd 算法
图论中一个经典问题就是求最短路.最为基础和最为经典的算法莫过于 Dijkstra 和 Floyd 算法,一个是贪心算法,一个是动态规划.这也是算法中的两大经典代表.用一个简单图在纸上一步一步演算,也是 ...
随机推荐
- [源码解析] 深度学习分布式训练框架 horovod (21) --- 之如何恢复训练
[源码解析] 深度学习分布式训练框架 horovod (21) --- 之如何恢复训练 目录 [源码解析] 深度学习分布式训练框架 horovod (21) --- 之如何恢复训练 0x00 摘要 0 ...
- uni-app仿抖音APP短视频+直播+聊天实例|uniapp全屏滑动小视频+直播
基于uniapp+uView-ui跨端H5+小程序+APP短视频|直播项目uni-ttLive. uni-ttLive一款全新基于uni-app技术开发的仿制抖音/快手短视频直播项目.支持全屏丝滑般上 ...
- 【PHP数据结构】链表的相关逻辑操作
链表的操作相对顺序表(数组)来说就复杂了许多.因为 PHP 确实已经为我们解决了很多数组操作上的问题,所以我们可以很方便的操作数组,也就不用为数组定义很多的逻辑操作.比如在 C 中,数组是有长度限制的 ...
- 注意!PHP中字符串与数字的比较
在日常开发过程中,运算符是我们每天都会接触到的.这个运算符中其实埋了非常多的坑,今天我们就来看下字符串和数字用比较需要注意的问题. 首先来看看这些代码: echo '"1234" ...
- PHP中的强制类型转换
学过静态语言开发的朋友对类型转换不会陌生,比如Java.C#.C++等.静态语言的好处就是变量强制必须指定类型,这也是编译的要求,所以大部分编译型的语言都会有强制变量类型的要求.而PHP据说也会在PH ...
- 第三方api接口
做为一个软件测试工程师,你要学习接口测试,需要练习,那么就要有调用的api,可以参考以下的文章. 国内7款API供应平台功能对比及详细介绍 https://blog.csdn.net/ishxiao/ ...
- python-requests包请求响应时间
p.p1 { margin: 0; font: 14px "Helvetica Neue"; color: rgba(17, 17, 17, 1) } p.p2 { margin: ...
- iSCSI 服务器搭建
一.简介 SCSI(Small Computer System Interface),小型计算机系统接口,是一种用于计算机及其周边设备之间(硬盘.软驱.光驱.打印机.扫描仪等)系统级接口的独立处理器标 ...
- 鸿蒙内核源码分析(静态站点篇) | 五一哪也没去就干了这事 | 百篇博客分析OpenHarmony源码 | v52.02
百篇博客系列篇.本篇为: v52.xx 鸿蒙内核源码分析(静态站点篇) | 五一哪也没去就干了这事 | 51.c.h.o 前因后果相关篇为: v08.xx 鸿蒙内核源码分析(总目录) | 百万汉字注解 ...
- 踩坑系列《八》解决Win10没有找到Hyper-v的错误
最近要安装docker,所以得开启Hyper属性面板,找了下,发现电脑上没有看到该属性. 在这之前,得先判断,你电脑是不是支持Hyper,打开cmd窗口,输入systeminfo 看看最下面Hyper ...