第K短路 嚴格第K短路

2022-09-15 06:27:09 字數 1577 閱讀 6446

所謂k短路,就是從s到t的第k短的路,第1短就是最短路。

如何求第k短呢?有一種簡單的方法是廣度優先搜尋,記錄t出佇列的次數,當t第k次出佇列時,就是第k短路了。但點數過大時,入佇列的節點過多,時間和空間複雜度都較高。

a*是在搜尋中常用的優化,一種啟發式搜尋。簡單的說,它可以用公式表示為f(n) = g(n) + f(n),其中,f(n)是從s經由節點n到t的估價函式,g(n)是在狀態空間中從s到n的實際代價,h(n)是從n到t的最佳路徑估計代價。在設計中,要保證h(n)<= n到t的實際代價,這一點很重要,h(n)越接近真實值,速度越快。

由於啟發函式的作用,使得計算機在進行狀態轉移時盡量避開不可能產生最優解的分支,而選擇相對較接近最優解的路徑進行搜尋,降低了時間和空間複雜度。

演算法過程:

1. 將圖反向,用dijstra+heap求出t到所有點的最短距離,目的是求所有點到點t的最短路,用dis[i]表示i到t的最短路,其實這就是a*的啟發函式,顯然:h(n)<= n到t的實際代價。

2. 定義估價函式。我們定義g(n)為從s到n所花費的代價,h(n)為dis[n],顯然這符合a*演算法的要求。

3. 初始化狀態。狀態中存放當前到達的點i,fi,gi。顯然,fi=gi+dis[i]。初始狀態為(s,dis[s],0),存入優先順序佇列中。

4. 狀態轉移。假設當前狀態所在的點v相鄰的點u,我們可以得到轉換:(v,fv,**)-->(u,fu+w[v][u],**+w[v][u])。

5. 終止條件。每個節點最多入佇列k次,當t出佇列k次時,即找到解。

例:poj2449

題意:裸的k短路。

#include #include #include #include using namespace std;

const int inf = 0x3f3f3f3f;

const int max = 1005;

int n,m;

int start,end,k;

struct edge

;edge e[100005];

int head[max],edgenum;

int dis[max];   //dis[i]表示從i點到end的最短距離

bool vis[max];

int cnt[max];

vectoropp_graph[max];

struct node

bool operator < (const node& a) const

}; void addedge(int from, int to, int w)

void dijikastra(int start)

}}} 

int a_star()

}return -1;} 

int main()

scanf("%d %d %d",&start,&end,&k);

if(start == end)

k++;

dijikastra(end);

int result = a_star();

printf("%d\n",result);

return 0;

}

第K短路(A 演算法)

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

第k短路和A

第一次接觸a 感覺好神奇。啟發函式 f x g x h x 比如初始狀態為s,目標狀態為t g x 表示從s到達狀態x所消耗的代價 h x 表示從x到達t所估算的代價 g x 表示s x可能出現的最小代價 h x 表示x t可能出現的最小代價 g x g x h x h x 好吧,上面全是概念。當g...

第K短路(模板)

沒太想明白 就當存在模板吧 include include include include include include include include include include using namespace std typedef long long ll const int maxn ...