POJ 2449 第K短路 A 演算法

2021-08-23 14:24:58 字數 1707 閱讀 2110

給定一張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...