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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

vector邻接表建图+dijkstra模板

發布時間:2025/3/21 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 vector邻接表建图+dijkstra模板 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文節點的編號從0開始計算
思路

dijkstra偽算法(未優化)源點到自己的距離為0,其余點到源點的距離為無窮大 記錄當前節點now為源點s 循環下面的步驟V次,V是結點的個數now標記已訪問遍歷now的出度(以now為起點出發的邊)如果連向的節點(姑且記為to)未被訪問,就“松弛”它松弛就是用“源點到to的距離”和“先到now再從now走到to的距離”的較小值更新前者偽代碼 dis[to] = min( dis[to], dis[now] + cost[now][to] )按順序遍歷所有 “未被訪問” 的節點找出離源點最近的那個,記錄為posnow = pos

這個復雜度是O(N^2)

C++實現

#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; using LL = long long; const int inf = 0x3f3f3f3f; const int MAX_E = 1e5+5; // 最大邊數 const int MAX_V = 1e4+5; // 最大節點數 int V, E; // 點、邊 struct edge{ int to, w; }; vector<edge> G[MAX_E]; bool vis[MAX_V]; int dis[MAX_V]; // 到源點的距離 void input(); void Build(int x, int y, int w); void dijkstra(int s); int main() {input();dijkstra(0);return 0; }void Build(int x, int y, int w = 1) {edge e; e.to = y; e.w = w;G[x].push_back(e); }void input() {int a,b,w;edge e;cin >> V >> E;for (int i = 0; i < E; i++){cin >> a >> b >> w; // 帶權//cin >> a >> b; // 不帶權Build(a, b, w);Build(b, a, w); // 無向} }void dijkstra(int s) {memset(dis, inf, sizeof(vis)); dis[s] = 0;memset(vis, false, sizeof(vis));int now = s;for (int i = 0; i < V; i++) // 循環V次,i沒有特殊意義{vis[now] = true;for (int j = 0; j < G[now].size(); j++) // 遍歷now的出度{if (!vis[G[now][j].to]) // 如果第j條出度連向的節點未被訪問{dis[G[now][j].to] = min( dis[G[now][j].to], dis[now] + G[now][j].w); // 松弛}}int Min = inf, pos = 0; // 找出未被訪問的節點中距離最短的那個,這一步可以堆優化,即用優先隊列避免遍歷V次for (int i = 0; i < V; i++) // 如果結點從1開始,遍歷[1,V]{if (!vis[i] && dis[i] < Min){Min = dis[i];pos = i;}}now = pos;}for (int i = 0; i < V; i++) printf("%d->%d=%d\n", s, i, dis[i]); }

借用書上的例圖,并將它看作是有向圖,當然只要把input函數里邊的第二個Build注釋掉就是有向圖了。

輸入

5 8 0 2 10 0 4 30 0 5 100 1 2 5 2 3 50 3 5 10 4 3 20 4 5 60

輸出

0->0=0 0->1=15 0->2=10 0->3=50 0->4=30

堆優化
原理是優化“尋找未被訪問的節點中離源點最近的那個”這一步。本來是遍歷,所以復雜度是O(N*N),如果改用優先隊列存儲這些節點,就可以將復雜度改進為O(NlogN)

參考了https://www.cnblogs.com/Renyi-Fan/p/7508098.html

堆優化偽算法 首先定義新的數據類型node,存儲點編號和點到源點的距離,也可以用pair代替 然后定義仿函數,為優先隊列提供自定義的出隊優先級源點入隊(入隊的是node對象,含編號和距離) 當隊列非空,循環下面步驟記錄隊首元素的點編號和距離 min_i, min_d出隊如果min_i 被訪問過,跳過這輪循環標記min_i已訪問遍歷min_i的出度記錄第i條邊連向的結點to,以及這條邊的權w如果to已被訪問,跳過此輪循環松弛node(to, dis[to]) 入隊

代碼

#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; using LL = long long; using PII = pair<int, int>; // first記錄點編號,second記錄邊權 const int inf = 0x3f3f3f3f; const int MAX_E = 1e5+5; // 最大邊數 const int MAX_V = 1e4+5; // 最大節點數 int V, E; // 點、邊 struct edge{ int to, w; }; struct cmp {bool operator () (const PII & P1, const PII &P2) const { return P1.second > P2.second; } // 距離短的優先 }; vector<edge> G[MAX_E]; bool vis[MAX_V]; int dis[MAX_V]; // 到源點的距離 void input(); void Build(int x, int y, int w); void dijkstra(int s); void dijkstra_2(int s); // 堆優化版本 int main() {input();dijkstra(0);cout << endl;dijkstra_2(0);return 0; }void Build(int x, int y, int w = 1) {edge e; e.to = y; e.w = w;G[x].push_back(e); }void input() {int a,b,w;edge e;cin >> V >> E;for (int i = 0; i < E; i++){cin >> a >> b >> w; // 帶權//cin >> a >> b; // 不帶權Build(a, b, w);Build(b, a, w); // 無向} }void dijkstra(int s) // 未優化 {memset(dis, inf, sizeof(vis)); dis[s] = 0;memset(vis, false, sizeof(vis));int now = s;for (int i = 0; i < V; i++) // 循環V次,i沒有特殊意義{vis[now] = true;for (int j = 0; j < G[now].size(); j++) // 遍歷now的出度{if (!vis[G[now][j].to]) // 如果第j條出度連向的節點未被訪問{dis[G[now][j].to] = min( dis[G[now][j].to], dis[now] + G[now][j].w); // 松弛}}int Min = inf, pos = 0; // 找出未被訪問的節點中距離最短的那個,這一步可以堆優化,即用優先隊列避免遍歷V次for (int i = 0; i < V; i++) // 如果結點從1開始,遍歷[1,V]{if (!vis[i] && dis[i] < Min){Min = dis[i];pos = i;}}now = pos;}for (int i = 0; i < V; i++) printf("%d->%d=%d\n", s, i, dis[i]); }struct node {int i; // 節點編號int d; // 到源點的距離node(int ii = -1, int dd = inf) : i(ii), d(dd){} };struct Cmp // 仿函數 {bool operator()(const node & n1, const node & n2) { return n1.d > n2.d; } // 距離短的優先出隊 };priority_queue<node, vector<node>, Cmp> Q;void dijkstra_2(int s) // 堆優化 {node n;int min_i, min_d; // 存距離源點最近的點編號和距離memset(dis, inf, sizeof(dis)); memset(vis, false, sizeof(vis));dis[s] = 0;Q.push(node(s, dis[s]));while (!Q.empty()){n = Q.top();Q.pop();min_i = n.i;min_d = n.d;if (vis[min_i]) continue; // 如果 min_i 已被訪問,不重復處理vis[min_i] = true;for (int i = 0; i < G[min_i].size(); i++) // 遍歷 min_i 的邊{int to = G[min_i][i].to; // min_i的第i條邊連向的節點int w = G[min_i][i].w; // 邊權if (!vis[to]) { dis[to] = min( dis[to], dis[min_i] + w ); // 松弛Q.push(node(to, dis[to]));}}}for (int i = 0; i < V; i++) printf("%d->%d=%d\n", s, i, dis[i]); }

附一組測試數據

6 10 0 1 5 0 3 7 1 2 4 2 0 8 2 5 9 3 2 5 3 5 6 4 3 5 5 4 1 5 0 3

輸出

0->0=0 0->1=5 0->2=8 0->3=7 0->4=4 0->5=30->0=0 0->1=5 0->2=8 0->3=7 0->4=4 0->5=3

總結

以上是生活随笔為你收集整理的vector邻接表建图+dijkstra模板的全部內容,希望文章能夠幫你解決所遇到的問題。

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