aStar算法求第k短路

A*的概念主意在于估计函数,f(n)=g(n)+h(n),f(n)是估计函数,g(n)是n节点的当前代价,h(n)是n节点的估计代价;而实际中,存在最优的估计函数f‘(n)=g‘(n)+h‘(n),那么显然我们在A*的估计中,h(n)<=h‘(n),否则你将搜不到最优解;(g(n)>=g‘(n)我还不怎么清楚为什么啊,大多数情况是g(n)=g‘(n),这个可以不用管吧。。)

求s->t的第k短路,

dist[x]为x->t的最短路 (这个只要反向建边,然后一次spfa,求出任意点到t点的距离即可

那么点x的g(x)=到达当前点的花费

h(x) = dist[x] ,    可以知道h(x)=h‘(x),所以可以保证搜到最优解。

每次出出队列的都是当前f(x)最小的点,

所以如果点x出队列, 那么就cnt[x]++,

当cnt[x]==k时,那么当前的f(x)就是第k短路,因为第一次出队列时,肯定是最短路上的点,第二次是次短路上的点,第k次,自然就是第k短路上的点了。

  1 #pragma warning(disable:4996)
  2 #pragma comment(linker, "/STACK:1024000000,1024000000")
  3 #include <stdio.h>
  4 #include <string.h>
  5 #include <time.h>
  6 #include <math.h>
  7 #include <map>
  8 #include <set>
  9 #include <queue>
 10 #include <stack>
 11 #include <vector>
 12 #include <bitset>
 13 #include <algorithm>
 14 #include <iostream>
 15 #include <string>
 16 #include <functional>
 17 #include <iostream>
 18 typedef __int64 LL;
 19 const int INF = 1 << 30;
 20
 21 /*
 22 */
 23 const int N = 1000 + 10;
 24 struct Node
 25 {
 26     int from, to, dis, next;
 27 }g[N*100];
 28 int head[N], e;
 29 int dist[N];
 30 bool vis[N];
 31 int cnt[N];
 32 void addEdge(int u, int v, int dis)
 33 {
 34     g[e].from = u;
 35     g[e].to = v;
 36     g[e].dis = dis;
 37     g[e].next = head[u];
 38     head[u] = e++;
 39 }
 40
 41 void spfa(int src, int n)
 42 {
 43     for (int i = 1;i <= n;++i)
 44         dist[i] = INF;
 45     std::queue<int> q;
 46     q.push(src);
 47     dist[src] = 0;
 48     while (!q.empty())
 49     {
 50         int u = q.front(); q.pop();
 51         vis[u] = false;
 52         for (int i = head[u];i + 1;i = g[i].next)
 53         {
 54             int v = g[i].to;
 55             if (dist[v] > dist[u] + g[i].dis)
 56             {
 57                 dist[v] = dist[u] + g[i].dis;
 58                 if (!vis[v])
 59                 {
 60                     vis[v] = true;
 61                     q.push(v);
 62                 }
 63             }
 64         }
 65     }
 66 }
 67 void init()
 68 {
 69     e = 0;
 70     memset(head, -1, sizeof(head));
 71 }
 72 void reverse()
 73 {
 74     memset(head, -1, sizeof(head));
 75     int te = e;
 76     e = 0;
 77     for (int i = 0;i < te;++i)
 78         addEdge(g[i].to, g[i].from, g[i].dis);
 79 }
 80 struct Node2
 81 {
 82     int to;
 83     int g;
 84     bool operator<(const Node2&rhs)const
 85     {
 86         return g + dist[to] > rhs.g + dist[rhs.to];
 87     }
 88 };
 89 /*
 90 因为每次出队列的都是最短的, 所以该点是第几次出队列,就表示是该点到终点的第k短路
 91 */
 92 int aStar(int src, int des, int k)
 93 {
 94     std::priority_queue<Node2> q;
 95     Node2 cur, tmp;
 96     cur.to = src;
 97     cur.g = 0;
 98     q.push(cur);
 99     while (!q.empty())
100     {
101         cur = q.top(); q.pop();
102         int u = cur.to;
103         cnt[u]++;
104         if (cnt[u] > k) continue;
105         if (cnt[u] == k)
106             return cur.g + dist[u];
107         for (int i = head[u];i + 1;i = g[i].next)
108         {
109             int v = g[i].to;
110             tmp.to = v;
111             tmp.g = cur.g + g[i].dis;
112             q.push(tmp);
113         }
114     }
115     return -1;
116 }
117 int main()
118 {
119     int n, m, src, des, k;
120     while (scanf("%d%d", &n, &m) != EOF)
121     {
122         init();
123         int u, v, dis;
124         for (int i = 1;i <= m;++i)
125         {
126             scanf("%d%d%d", &u, &v, &dis);
127             addEdge(v, u, dis);
128         }
129         scanf("%d%d%d", &src, &des, &k);
130         spfa(des, n);
131         reverse();
132         if (src == des)k++;//如果起点等于终点,那么最短路其实是什么都不走
133         int ans = aStar(src, des, k);
134         printf("%d\n", ans);
135     }
136     return 0;
137 }

时间: 2024-10-05 20:48:12

aStar算法求第k短路的相关文章

A* 算法求第 K 短路

一种具有 \(f(n)=g(n)+h(n)\) 策略的启发式算法能成为 A* 算法的充分条件是: 搜索树上存在着从起始点到终了点的最优路径. 问题域是有限的. 所有结点的子结点的搜索代价值 \(>0\). \(h(n) \le h^\ast (n)\) (\(h^\ast (n)\) 为实际问题的代价值). Remmarguts' Date 求 S 到 T 的第 K 短路. 思路: (1) 将有向图的所有边反向,以原终点T为源点,求解T到所有点的最短距离. (2) 新建一个优先队列,将源点S加入

&lt;学习笔记&gt; A*算法求第k短路

一条前往题面的隧道 简洁题面 第一行给出N(点数),M(边数)(1 <= N <= 1000, 0 <= M <= 100000).. 下面的M行每行给出三个数Ai,Bi,Ti,表示从A到B有一条权值为T的单向边. 最后给出S,T,K,表示求S到T的第K短路. special: 起点与终点相同时,S–>S (d=0) 不能算作一条路. 题目会给出多组数据. 即使有好几条路到T的距离都相同,它们仍被记为不同的路. 正解 A*算法 记g[i]为起点s到i的距离,h[i] (期望值

poj 2449 Remmarguts&#39; Date 求第k短路 Astar算法

=.=好菜 #include <iostream> #include <cstdio> #include <string.h> #include <cstring> #include <queue> using namespace std; const int N = 1e3+10; const int M = 100000+10; typedef long long ll; const ll INF = 1e15; int n,m,head[N

A*算法的认识与求第K短路模板

现在来了解A*算法是什么 现在来解决A*求K短路问题 在一个有权图中,从起点到终点最短的路径成为最短路,第2短的路成为次短路,第3短的路成为第3短路,依此类推,第k短的路成为第k短路.那么,第k短路怎么求呢? 对于第k短路,可以想到的一个比较朴素的算法就是广度优先搜索,使用优先队列从源点s进行广搜,当第k次搜索到终点t时,所的长度即所求但是这种方法在运行过程中会产生特别多的状态,当图比较简单.k比较小时,可以一试,但是当k较大或者图中点数较多时,会面临爆栈的危险.目前使用比较多的算法是单源最短路

poj 2449 Remmarguts&#39; Date A*+spfa求第k短路

题意: 经典的第k短路,A*算法的经典应用之一. 分析: A*,已走的路程g+到终点的最短距离为启发函数,搜索过程中不判重,第k次到t节点时就求出了第k短路. 代码: //poj 2449 //sep9 #include <iostream> #include <queue> using namespace std; const int maxN=1024; const int maxM=100024; int n,m,s,t,k,e,ne; int head[maxN],nhea

POJ 2449 求第K短路

第一道第K短路的题目 QAQ 拿裸的DIJKSTRA + 不断扩展的A* 给2000MS过了 题意:大意是 有N个station 要求从s点到t点 的第k短路 (不过我看题意说的好像是从t到s 可能是出题人写错了) 从这题中还真的学到了很多1.第k短路的算法 A* 还有用边表实现dij (注:以下部份资料来源于网上)所谓A*就是启发是搜索 说白了就是给搜索一个顺序使得搜索更加合理减少无谓的搜索. 如何来确定搜索的顺序?..也就是用一个值来表示 这个值为f[n]..每次搜索取f[x]最小的拓展 那

POJ2449Remmarguts&#39; Date(A*算法求第K小路)

Remmarguts' Date Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 21084   Accepted: 5740 Description "Good man never makes girls wait or breaks an appointment!" said the mandarin duck father. Softly touching his little ducks' head, h

POJ 2499 A*求第K短路

DES就是给你一个图.然后给你起点和终点.问你从起点到终点的第K短路. 第一次接触A*算法. // 大概懂思路了.A*算法需要的估价函数里的两个函数.一个是起点到当前点的消耗. //一个是当前点到目标点的估测消耗.所以需要用Dijstra或者Spfa求出目标点到所有点的最短路. //然后就可以用A*算法来求了. // 确实.学了位运算.链式表. #include<cstdio> #include<iostream> #include<queue> #include<

FLOyd算法 求任意最短路

此算法由Robert W. Floyd(罗伯特·弗洛伊德)于1962年发表在"Communications of the ACM"上.同年Stephen Warshall(史蒂芬·沃舍尔)也独立发表了这个算法.Robert W.Floyd这个牛人是朵奇葩,他原本在芝加哥大学读的文学,但是因为当时美国经济不太景气,找工作比较困难,无奈之下到西屋电气公司当了一名计算机操作员,在IBM650机房值夜班,并由此开始了他的计算机生涯. 作者:ahalei来源:51CTO博客|2014-03-26