日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第K短路+严格第K短路

發布時間:2023/12/15 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第K短路+严格第K短路 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??所謂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,gv)-->(U,fu+w[v][u],gv+w[v][u])。

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

?

????例:POJ2449

????題意:裸的K短路。

#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int INF = 0x3f3f3f3f; const int MAX = 1005; int n,m; int start,end,k; struct Edge {int w;int to;int next; }; Edge e[100005]; int head[MAX],edgeNum; int dis[MAX]; ? //dis[i]表示從i點到end的最短距離 bool vis[MAX]; int cnt[MAX]; vector<Edge> opp_Graph[MAX];struct Node {int f,g; ? ?//f = g+dis[v]int v; ? ? ?//當前到達的節點Node(int a, int b,int c):f(a),g(b),v(c){}bool operator < (const Node& a) const{return a.f < f;} };void addEdge(int from, int to, int w) {e[edgeNum].to = to;e[edgeNum].w = w;e[edgeNum].next = head[from];head[from] = edgeNum++; }void dijikastra(int start) {int i;memset(vis,0,sizeof(vis));for(i = 1; i <= n; i++)dis[i] = INF;dis[start] = 0;priority_queue<Node> que;que.push(Node(0,0,start));Node next(0,0,0);while(!que.empty()){Node now = que.top();que.pop();if(vis[now.v]) ? ? ? ? ? ? ?//從集合T中選取具有最短距離的節點continue;vis[now.v] = true; ? ? ? ? ?//標記節點已從集合T加入到集合S中for(i = 0; i < opp_Graph[now.v].size(); i++) ? ?//更新從源點到其它節點(集合T中)的最短距離{Edge edge = opp_Graph[now.v][i];if(!vis[edge.to] && dis[now.v] + edge.w < dis[edge.to]) ? ? //加不加前面的判斷無所謂{dis[edge.to] = dis[now.v] + edge.w;next.f = dis[edge.to];next.v = edge.to;que.push(next);}}} }int A_Star() {int i;priority_queue<Node> que;if(dis[start] == INF)return -1;que.push(Node(dis[start],0,start));Node next(0,0,0);while(!que.empty()){Node now = que.top();que.pop();cnt[now.v]++;if(cnt[end] == k) return now.f;//嚴格最短路的判斷條件為 cnt[end] == k&&now.f>min(zuiduanlu)if(cnt[now.v] > k)continue;for(i = head[now.v]; i != -1; i = e[i].next){next.v = e[i].to;next.g = now.g + e[i].w;next.f = next.g + dis[e[i].to];que.push(next);}}return -1; }int main() {int i;int from,to,w;edgeNum = 0;memset(head,-1,sizeof(head));memset(opp_Graph,0,sizeof(opp_Graph));memset(cnt,0,sizeof(cnt));scanf("%d %d",&n,&m);Edge edge;for(i = 1; i <= m; i++){scanf("%d %d %d",&from,&to,&w);addEdge(from,to,w);edge.to = from;edge.w = w;opp_Graph[to].push_back(edge);}scanf("%d %d %d",&start,&end,&k);if(start == end)k++;dijikastra(end);int result = A_Star();printf("%d\n",result);return 0; }

?

總結

以上是生活随笔為你收集整理的第K短路+严格第K短路的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。