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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

Yen 的k_shortest paths 算法的C++实现

發布時間:2025/4/16 c/c++ 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Yen 的k_shortest paths 算法的C++实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

具體介紹見:https://en.wikipedia.org/wiki/Yen%27s_algorithm

還有具體步驟見:https://blog.csdn.net/sharpdew/article/details/446510?tdsourcetag=s_pctim_aiomsg

我也不知道我對這個算法理解是否完全正確,但是大體的數據結構和邏輯是正確的,希望大家指點,后期我更理解了,會做相應修改。

在這個算法里需要改進的地方是:我沒有用堆去插入,這個等有時間再做?

#include<vector> #include<string> #include<math.h> #include<algorithm> #include <iostream> #include<stack> using namespace std; static const unsigned int INF(std::numeric_limits<int>::max()); static const unsigned undefined = INF;class K_Shortest_Path { public:vector<vector<unsigned int>> run(const unsigned int kPath, // K Pathconst vector<vector<unsigned int>>& NW, // networkconst unsigned int src, // source nodeconst unsigned int dst); // destination node };// //結構體用于保存兩點之間的最短路徑和長度 // class DijPath { public:vector<unsigned int> onePath;int cost;bool operator <(const DijPath &n2);//判斷兩條路徑是否相等bool operator ==(const DijPath &n2); };bool DijPath::operator <(const DijPath &n2) {return cost < n2.cost; } //判斷兩條路徑是否相等 bool DijPath::operator ==(const DijPath &n2) {if (onePath.size() == n2.onePath.size()){for (unsigned int i = 0; i < onePath.size(); i++){if (onePath[i] != n2.onePath[i])return false;}return true;}return false; }// //最短路徑算法,返回一個DijPath結構體 // DijPath dijkstra(const vector<vector<unsigned int>> &NW,const int src,const int dst ) {//圖中節點個數unsigned int sizeNW = NW.size(); //知道每一個節點都被訪問過結束vector<bool> visited(sizeNW); //到達dst頂點的最短路徑的前一個頂點vector<unsigned int> prev(sizeNW); //下一個距離當前訪問過的最小的一個點int minPos = 0; //用于記錄每個頂點到源節點的距離,如果最終len[dst]=INF,//說明src和dst不可到達,講cost設置為INF,用于ksp做判斷舍棄這條路徑vector<unsigned int> len(sizeNW);for (unsigned int i = 0; i < NW.size(); i++) //初始化{visited[i] = false; //一開始均被訪問len[i] = NW[src][i];prev[i] = INF;}//初始節點被設置為訪問過visited[src] = true;for (unsigned int i = 0; i < sizeNW; ++i) {unsigned int min = INF; //記錄訪問過的節點到沒訪問過的節點的最小路徑長度for (unsigned int j = 0; j < sizeNW; ++j){if (!visited[j] && min > len[j]){minPos = j; //記錄找到了下一個節點min = len[j];}}visited[minPos] = true;for (unsigned int j = 0; j < sizeNW; ++j){//如果j節點沒有被訪問過,且通過j節點發現到其他節點更短的len[j]值if (!visited[j] && len[j] > (len[minPos] + NW[minPos][j])){prev[j] = minPos;len[j] = len[minPos] + NW[minPos][j];}}}unsigned int beforeVertex = dst;//通過一個棧將prev[]中的節點給倒過去,實現正序排列stack<unsigned int> st;while (prev[beforeVertex] != INF){st.push(beforeVertex);beforeVertex = prev[beforeVertex];}st.push(beforeVertex);//st棧中保存了第二個節點到dst的最短路徑的正序DijPath oneDijPath;oneDijPath.onePath.resize(st.size() + 1);oneDijPath.onePath[0] = src;for (unsigned int i = 1; !st.empty(); i++){oneDijPath.onePath[i] = st.top();st.pop();}oneDijPath.cost = len[dst]; //返回最短路徑的值,如果不可到達,設置為INFreturn oneDijPath; }// //用于裁剪掉kSP所有路徑中root節點后面的所有的邊和當前路徑的前一條邊 //返回一個vector<vector<unsigned int>>的被裁剪后的圖 vector<vector<unsigned int>> cutEdge(const vector<vector<unsigned int>>& NW,vector< DijPath> kSPCost,unsigned int root) {vector<vector<unsigned int>>NWCopy = NW;for (unsigned int i = 0; i < kSPCost.size(); i++){for (unsigned int j = 0; j < kSPCost[i].onePath.size(); j++){if (kSPCost[i].onePath[j] == root){unsigned int nextVertex = kSPCost[i].onePath[j + 1];if (j >= 1){unsigned int beforeVertex = kSPCost[i].onePath[j - 1];NWCopy[root][beforeVertex] = INF;}NWCopy[root][nextVertex] = INF; //設置為不可連接break;}}}return NWCopy;}// //Yen_k-shortest-path // vector<vector<unsigned int>> K_Shortest_Path::run(const unsigned int kPath, // K Pathconst vector<vector<unsigned int>>& NW, // networkconst unsigned int src, // source nodeconst unsigned int dst) // destination node{vector<vector<unsigned int>>NWCopy = NW;vector< DijPath> kSPCost(1); //不僅包含最短路徑,還包含路徑長度vector< DijPath>B; //一個用于記錄沒有上一代通過裁剪邊得到的下一代路徑DijPath newPath = dijkstra(NW, src, dst); //第一條最短路徑vector<vector<unsigned int>> kSP; //返回的路徑if (newPath.cost==INF) //判斷最開始是否可以到達{kSP.resize(0);return kSP;}kSPCost[0] = newPath; //用于儲存找到的路徑vector<unsigned int>forwardPath; //記錄裁剪邊前面的int nowCost; //用于記錄到裁剪掉邊前面一段路徑的長度for (unsigned int k = 1; k < kPath; k++) //用于找到所有的kPath{nowCost = 0;bool flag = false;//將這一代中B的節點加到kSP中去,當時必須等待上一代的所有邊遍歷完成for (unsigned int i = 0; i < B.size() && kSPCost.size() < kPath&&kSPCost.size() >= k - 1; i++){kSPCost.push_back(B[i]);flag = true;}if (flag) //如果將B的路徑加到A中,就置空B{B.resize(0);}//找不到路徑了,直接返回if (kSPCost.size() < k){sort(kSPCost.begin(), kSPCost.end());for (unsigned int i = 0; i < kSPCost.size(); i++){kSP.push_back(kSPCost[i].onePath);}return kSP;}forwardPath.resize(0);for (unsigned int i = 0; i < kSPCost[k - 1].onePath.size() - 1; i++) //用于第k-1條路徑所有的邊嘗試去除去{forwardPath.push_back(kSPCost[k - 1].onePath[i]);if (i != 0){unsigned int forwardVertex = kSPCost[k - 1].onePath[i];unsigned int nextVertex = kSPCost[k - 1].onePath[i - 1];nowCost += NW[forwardVertex][nextVertex];}NWCopy = cutEdge(NW, kSPCost, kSPCost[k - 1].onePath[i]);//找到一條從剪掉邊的前面的那個節點到終點的一條最短路徑DijPath secondPath = dijkstra(NWCopy, kSPCost[k - 1].onePath[i], dst);if (secondPath.cost > 100000)//判斷兩點不可以到達{continue;}//找到新的路徑newPath.onePath = forwardPath;for (unsigned int j = 1; j < secondPath.onePath.size(); j++){newPath.onePath.push_back(secondPath.onePath[j]);}newPath.cost = secondPath.cost + nowCost;//判斷newPath是不是已經存在了secondPath.onePath.resize(0);DijPath tmp;tmp.cost = newPath.cost;bool flag = true;for (unsigned int j = 0; j < kSPCost.size(); j++){tmp.onePath = kSPCost[j].onePath;if (tmp == newPath){flag = false; //已經存在了break;}}if (flag) //不存在,加到新的路徑中{B.push_back(newPath);}if (kSPCost.size() >= kPath){sort(kSPCost.begin(), kSPCost.end());for (unsigned int i = 0; i < kSPCost.size(); i++){kSP.push_back(kSPCost[i].onePath);}return kSP;}}}sort(kSPCost.begin(), kSPCost.end());for (unsigned int i = 0; i < kSPCost.size(); i++){kSP.push_back(kSPCost[i].onePath);}return kSP; }int main(){const string funcReturn("int");const string funcName("main(int argc, char *argv[])");try {//unsigned int NODE = 5;vector<vector<unsigned int>> NW(NODE, vector<unsigned int>(NODE, 0));//vector<vector<unsigned int>> NW = {// {0, 0, 0, 1, 1}, // A(0)// {0, 0, 1, 0, 1}, // B(1)// {0, 1, 0, 1, 1}, // C(2)// {1, 0, 1, 0, 1}, // D(3)// {1, 1, 1, 1, 0}, // E(4)//};NW 2vector<vector<unsigned int>> NW = {{0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0},{1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0},{1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0},{1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0},{0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1},{0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0},{1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0},{0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1},{0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1},{0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1},{0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0},};for (unsigned int i(0); i < NW.size(); i++) {for (unsigned int j(0); j < NW.size(); j++) {if (NW[i][j] == 0) {NW[i][j] = INF;}}}//創建networkcout << "Network: " << endl;for (unsigned int i(0); i < NW.size(); i++) {cout << " > ";for (unsigned int j(0); j < NW[i].size(); j++) {if (NW[i][j] !=INF)cout << " " << NW[i][j];elsecout << " " << 0;}cout << endl;}// K-Shortest Pathunsigned int kPath = 10;cout << endl << "K-Shortest Path (" << kPath << ")" << endl;K_Shortest_Path KSP;vector<vector<unsigned int>> kSP = KSP.run(kPath, NW, 0, 1);cout << endl << "Result (0 --> 1): " << endl;cout << " > Number of path: " << kSP.size() << endl;for (unsigned int i(0); i < kSP.size(); i++) {cout << " >> " << (i + 1) << ":";for (unsigned int j(0); j < kSP[i].size(); j++) {cout << " " << kSP[i][j];}cout << endl;}// vector<unsigned int> ary1(NODE, 0);// vector<vector<unsigned int>> ary2(NODE, ary1);}//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// 例外処理// エラーが発生した場合にエラーを受け取って表示する処理//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// 入出力ストリームでの例外処理catch (std::ios_base::failure& err) {cout << endl << endl;cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-" << endl;cout << "Exception : std::ios_base::failure" << endl;cout << " >> " << funcReturn << " " << funcName << endl;cout << "Error Content:" << endl<< err.what() << endl;}// 範囲外へのアクセスによる例外処理(実行前)catch (std::out_of_range& err) {cout << endl << endl;cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-" << endl;cout << "Exception : std::out_of_range" << endl;cout << " >> " << funcReturn << " " << funcName << endl;cout << "Error Content:" << endl<< err.what() << endl;}// 引數の値が不正な場合の例外処理(実行前)catch (std::invalid_argument& err) {cout << endl << endl;cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-" << endl;cout << "Exception : std::invalid_argument" << endl;cout << " >> " << funcReturn << " " << funcName << endl;cout << "Error Content:" << endl<< err.what() << endl;}// 最大の長さを超える長さの値による例外処理(実行前)catch (std::length_error& err) {cout << endl << endl;cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-" << endl;cout << "Exception : std::length_error" << endl;cout << " >> " << funcReturn << " " << funcName << endl;cout << "Error Content:" << endl<< err.what() << endl;}// その他の実行前に発生する例外処理(実行前)catch (std::domain_error& err) {cout << endl << endl;cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-" << endl;cout << "Exception : std::domain_error" << endl;cout << " >> " << funcReturn << " " << funcName << endl;cout << "Error Content:" << endl<< err.what() << endl;}// 數値演算を行った結果、アンダーフローが発生したときの例外処理(演算関係)catch (std::underflow_error& err) {cout << endl << endl;cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-" << endl;cout << "Exception : std::underflow_error" << endl;cout << " >> " << funcReturn << " " << funcName << endl;cout << "Error Content:" << endl<< err.what() << endl;}// 數値演算を行った結果、オーバーフローが発生したときの例外処理(演算関係)catch (std::overflow_error& err) {cout << endl << endl;cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-" << endl;cout << "Exception : std::overflow_error" << endl;cout << " >> " << funcReturn << " " << funcName << endl;cout << "Error Content:" << endl<< err.what() << endl;}// 演算処理の過程において、有効な範囲外の値となったときに発生する例外処理(演算関係)catch (std::range_error& err) {cout << endl << endl;cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-" << endl;cout << "Exception : std::range_error" << endl;cout << " >> " << funcReturn << " " << funcName << endl;cout << "Error Content:" << endl<< err.what() << endl;}// メモリ確保失敗の例外処理catch (std::bad_alloc& err) {cout << endl << endl;cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-" << endl;cout << "Exception : std::bad_alloc" << endl;cout << " >> " << funcReturn << " " << funcName << endl;cout << "Error Content:" << endl<< err.what() << endl;}// 前述していない例外処理を受け取るcatch (...) {cout << endl << endl;cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-" << endl;cout << "Exception : unknown" << endl;cout << " >> " << funcReturn << " " << funcName << endl;}return 0; }

?

總結

以上是生活随笔為你收集整理的Yen 的k_shortest paths 算法的C++实现的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 国产免费久久精品国产传媒 | 欧美肉丝袜videos办公室 | 成人毛片在线免费观看 | 成人在线激情视频 | 波多野结衣理论片 | 亚洲国产精品系列 | 黄色大片视频网站 | 自拍偷拍第二页 | 超爽视频 | 91免费看国产 | 国产无码精品在线播放 | 男人天堂成人 | 国产精品国产一区二区三区四区 | 国产午夜无码视频在线观看 | 91黄色小视频 | 性巴克成人免费网站 | 日韩午夜电影网 | 欧美日韩国产在线观看 | 国产老熟妇精品观看 | 在线视频免费观看一区 | 中文字幕在线观看一区 | 免费在线观看a视频 | 亚洲图区综合 | 国产污污视频 | 亚洲码在线观看 | 久久精品韩国 | 狠狠插综合 | 久久国产片 | 在线中文字幕视频 | 日韩欧美色| 91在线视频播放 | 国产精品破处 | 久久久穴 | 神马午夜我不卡 | 亚洲大尺度av | 偷偷色噜狠狠狠狠的777米奇 | 午夜精品毛片 | 亚洲视频在线观看视频 | 懂色av中文字幕 | 久久久久二区 | 欧美在线激情 | 久久精品av | 国产午夜在线 | 亚洲色图网友自拍 | 伦伦影院午夜理伦片 | 99久久久精品免费观看国产 | 超碰国产在线观看 | 亚洲自拍第二页 | 欧美视频免费看欧美视频 | 男人的天堂亚洲 | 亚洲精品乱码 | 免费在线观看网址入口 | 99riav国产| 91麻豆精品国产午夜天堂 | 国产精品无码专区 | 欧美群交射精内射颜射潮喷 | 曰女同女同中文字幕 | av高清一区 | 夜夜夜操 | 天堂а√在线中文在线新版 | 亚洲最新中文字幕 | 精品人妻一区二区三区日产乱码 | 无码成人精品区在线观看 | 懂色av蜜臀av粉嫩av喷吹 | 国产午夜在线播放 | 成人乱人乱一区二区三区 | 97小视频 | 一边顶弄一边接吻 | 国产夜色精品一区二区av | 少妇天堂网| 久久久久99精品成人片毛片 | 不卡av免费 | 亚洲综合日韩精品欧美综合区 | 欧美日韩人妻精品一区 | 丰满少妇xoxoxo视频 | 精品国产亚洲av麻豆 | 69色 | 一级在线免费视频 | 丰满熟妇被猛烈进入高清片 | 美女100%露胸无遮挡 | 久一在线视频 | 91九色丨porny丨国产jk | 亚洲区免费 | 污色视频| 蜜臀久久99静品久久久久久 | 波多野吉衣一区二区三区 | 高跟肉丝丝袜呻吟啪啪网站av | 香蕉视频亚洲 | 网友自拍视频 | www性| 国产丝袜精品视频 | 免费成人电影在线观看 | 亚洲专区在线 | 伊人96| 能看的av网站 | 久久久久久久蜜桃 | 天天操天天射天天爱 | 国产欧美一区二区三区在线老狼 | 国产福利小视频在线观看 |