第K短路(A (astar)演算法)

2021-10-03 11:37:03 字數 1809 閱讀 3467

給定一張n個點(編號1,2…n),m條邊的有向圖,求從起點s到終點t的第k短路的長度,路徑允許重複經過點或邊。

注意:每條最短路中至少要包含一條邊。

輸入格式

第一行包含兩個整數n和m。

接下來m行,每行包含三個整數a,b和l,表示點a與點b之間存在有向邊,且邊長為l。

最後一行包含三個整數s,t和k,分別表示起點s,終點t和第k短路。

輸出格式

輸出佔一行,包含乙個整數,表示第k短路的長度,如果第k短路不存在,則輸出「-1」。

資料範圍

1≤s,t≤n≤1000

0≤m≤105

1≤k≤1000

1≤l≤100

輸入樣例:

2 2

1 2 5

2 1 4

1 2 2

輸出樣例:

14
思路:a*演算法就是在bfs上加了乙個啟發函式,也就是乙個距離的估值,從而使搜尋更直接,更準確,避免了許多不必要的搜尋,a*演算法的一條定理,只要估計值f(s)<= 實際距離d(s),每次從優先佇列中bfs之前取出的用來擴充套件的就是當前最小距離,因為最短距離一定<=真實距離,所以可以:

1、用終點t作為dijkstra的起點在反向圖中跑一遍dijkstra算出每個點到終點的最短距離,作為那個點的估值。

2、用astar演算法,然後根據估值排序(把估計值作為pair的first放到優先佇列就可以實現按估值排序了),從s開始bfs,每次的取出的就是最短,第k次到達t點就是第k短路了。

完整**:

#include #include #include #define pll pair#define plll pair#define x first

#define y second

using namespace std;

const int maxm=2e5+5,maxn=1e3+5;

int head[maxn],e[maxm],net[maxm],w[maxn],to[maxm],rhead[maxn];

int s,t,k;

int cnt,n,m,dis[maxn],vis[maxn],f[maxn];//f[i]記錄到達編號為i的點估計的距離(本題取的最短距離),所以f=dis

void addedge(int *head,int a,int b,int l)

void dijkstra()

);//從終點開始往回擴充套件,由此計算出每個點距離t的最短距離作為估值f

dis[t]=0;//dijkstra演算法,起點的dis初始值為0!

while(heap.size())});//first存放當前點的估值f(估計距離),priority_queue按first這個估計值排序(從小到大),second.first為當前點的真實距離,second.second為當前點的編號

while(heap.size())});//每次擴充套件時,當前最短距離+邊權+估值作為下一次的估值,當前真實距離d+w[i],當前點編號v}}

return -1;

}int main()

scanf("%d%d%d",&s,&t,&k);

if(s==t) k++;//當s==t時,最短是自己到自己的,但該方案沒有邊,這裡不算做一條最短路,所以除去這條,下條最短算作第一短,應該是求k+1短

dijkstra();

int ans=astar();

cout

}

第K短路(A 演算法)

對於無向圖 spfa a 演算法 先用spfa求目標結點到各個結點的最短路徑 然後,取g x 為從初始結點到當前結點x的路徑長度,h x 為從x結點到目標結點的最短路徑長度,即h x 取dis x 即可,估價函式f x g x h x 對於有向圖 spfa a 演算法 顯然應將有向邊取反,然後求目標...

第K短路 嚴格第K短路

所謂k短路,就是從s到t的第k短的路,第1短就是最短路。如何求第k短呢?有一種簡單的方法是廣度優先搜尋,記錄t出佇列的次數,當t第k次出佇列時,就是第k短路了。但點數過大時,入佇列的節點過多,時間和空間複雜度都較高。a 是在搜尋中常用的優化,一種啟發式搜尋。簡單的說,它可以用公式表示為f n g n...

A 演算法求第k短路徑

a 演算法是一類貪心演算法,其可以用於尋找最優路徑。我們可以利用a 演算法來求第k短路徑。一條路徑可以由兩部分組成,第一部分是乙個從出發到達任意點的任意路徑,而第二部分是從第一部分的末端出發,到終點的最短路徑。兩部分正好可以組成一條路徑,且每一條路徑都可以分解這兩部分 允許任意一部分為空 因此當我們...