給定一張n個點,m條邊的有向圖,求從起點到終點t的第k短路的長度。
求第k短路,我們先回憶一下dijkstra求最短路的方法。
每次鬆弛了乙個節點,則將該節點放入優先佇列,然後在取優先佇列的第乙個點,即源點到該點距離最短的點,再用該點去鬆弛其他的點。最終求出的距離就是單源最短距離。
換句話說,就是用優先佇列bfs對整張圖進行遍歷,當乙個點被第一次取出時,此時的距離便是該點的最短距離。
由此,我們便得知了求第k短路的方法。即對於任意頂點 i ,當頂點 i 被第k次取出時,此時的距離便是該點的第k短路。
但是,如果直接用優先佇列的bfs去求第k短路,無疑會造成大量的冗餘搜尋。因此我們需要用a*演算法,即啟發式演算法進行優化。
啟發式演算法的核心:
1.設立乙個估價函式,對於每乙個狀態,估價函式的值就是該狀態到目標狀態所需的花費。注意這個花費必須小於真實花費,否則程式會出錯。
2.對每一次搜尋到的狀態,我們定義該狀態的值為「該狀態的花費」+「該狀態到目標狀態所需的值」,即估價函式在該狀態下的值。
3.然後我們每次取出狀態值最小的點進行bfs,即可優化搜尋。
由此,a*,即是改變bfs的搜尋方向,使得我們更快地搜到目標值。
我們再回到本題,在該題中,估價函式應該是該點到目標點的距離,此時估價花費 <= 真實花費,因此可行。
我們定義每個點的值為當前到該點的距離 + 該點到目標點的距離,然後再進行bfs優先佇列搜尋,即為a*演算法在本題的應用。
#include #include #include #include #include #define rep(i,a,b) for(int i = a;i <= b;i++)
using namespace std;
const int m = 1e5+100;
const int n = 2000;
const int inf = 0x3f3f3f3f;
int n,m,s,t,k;
struct edgee[m],ef[m];
int head[n],headf[n],tot,totf;
int dis[n],book[n],dist[n];
struct potmp;
bool operator < (po x,po y) //優先佇列只能過載 <
void init()
void add(int x,int y,int w)
void addf(int x,int y,int w)
void spfa(int x)
}} book[p] = 0;
q.pop(); }}
int bfs()
} if(val!=k)
}int main()
scanf("%d%d%d",&s,&t,&k);
spfa(t);
printf("%d\n",bfs());
} return 0;}/*
2 10
1 2 42
1 2 1
1 1 79
2 2 65
2 2 82
1 2 92
2 1 28
2 1 5
2 1 93
2 1 17
1 2 1000
*/
POJ 2449 求第K短路
第一道第k短路的題目 qaq 拿裸的dijkstra 不斷擴充套件的a 給2000ms過了 題意 大意是 有n個station 要求從s點到t點 的第k短路 不過我看題意說的好像是從t到s 可能是出題人寫錯了 從這題中還真的學到了很多 1.第k短路的演算法 a 還有用邊表實現dij 注 以下部份資料...
poj 2449 第k短路徑
思路 利用乙個估計函式g i dis i len。其中len為佇列出來的點當前已經走了的距離。dis i 為該點到終點的最短路徑。這樣我們只要將點按g i 的公升序在佇列你排序,每次取出最小的g i 值的點。其意義就是每次找最短的能到終點的點。第一次找到就是最短路徑,第二次就是就是第二短,第三次就是...
A 演算法(k短路)模板 poj 2449
a 演算法就是在bfs擴充套件的時候優化了一下,對於乙個點x,當前花費a,到終點花費h x 那a h x 就可以視作它這個點的總花費,這就可以在bfs時優先遍歷花費少的點 include include include includeusing namespace std define ll lon...