hdu2066 dijkstra多源點多終點求最短路徑
阿新 • • 發佈:2018-12-22
dijkstra演算法的思路:
(1)找到最短距離已經確定的頂點,從它出發更新相鄰頂點的最短距離
(2)此後不再關心(1)中最短距離已經確定的頂點
最開始時只有起點的最短距離是確定的,而在未使用過的頂點中,距離d[i]最小的頂點就是最短距離已經確定的頂點,在不存在負邊的情況下d[i]不會在之後的更新中變小。 存在負邊則無法使用dijkstra
使用優先佇列實現:
#include "pch.h" #pragma warning (disable:4996) #include<stdio.h> #include <iostream> #include<cstring> #include<algorithm> #include<vector> #include<queue> using namespace std; const int INF = 100000; const int maxn = 1000 + 50; struct edge { int to, cost; }; typedef pair<int, int> P;//first是最短距離 second是頂點編號 vector<edge>G[maxn]; int d[maxn]; int T, S, D; int desti[maxn]; void dijkstra(int s) { priority_queue<P, vector<P>, greater<P> >que; //指定greater<P>引數,堆按照first從小到大的順序取出值 fill(d, d + maxn, INF); d[s] = 0; que.push(P(0, s)); while (!que.empty()) { P p = que.top();que.pop(); //取出佇列中距離最小的頂點 int v = p.second; if (d[v] < p.first)continue; for (int i = 0;i < G[v].size();i++) { edge e = G[v][i]; if (d[e.to] > d[v] + e.cost) {//如果有重邊,選擇邊權最小的 d[e.to] = d[v] + e.cost; que.push(P(d[e.to], e.to)); } } } } int main() { //freopen("datain.txt","r",stdin); while (~scanf("%d%d%d", &T, &S, &D)) { int MINI = INF; for (int i = 0;i < maxn;i++) G[i].clear(); for (int i = 0;i < T;i++) { edge e, e1; int from; scanf("%d%d%d", &from, &e.to, &e.cost); G[from].push_back(e); e1.to = from;e1.cost = e.cost; G[e.to].push_back(e1);} //無向圖正反方向都要輸入 for (int i = 0;i < S;i++) { int city; scanf("%d", &city); edge e; e.to = city; e.cost = 0; G[0].push_back(e);} for (int i = 0;i < D;i++) scanf("%d", &desti[i]); dijkstra(0); for (int i = 0;i < D;i++) { MINI = min(MINI, d[desti[i]]); } cout << MINI << endl; } }
而圖中存在負邊的情況,則需要使用Bellman-Ford或者Floyd-Warshall演算法
Bellman-Ford:
#include "pch.h" #pragma warning (disable:4996) #include<stdio.h> #include <iostream> #include<cstring> #include<algorithm> #include<vector> #include<string> #define INF 1000000 const int maxn = 1000 + 5; using namespace std; int d[maxn];//最短距離 int V, E;//頂點數 邊數 struct edge{ int from, to, cost; }edges[maxn]; void shortest_path(int s) { for (int i = 0;i < V;i++) d[i] = INF; d[s] = 0; while (true) { bool update = false; for (int i = 0;i < E;i++) { edge e = edges[i]; if (d[e.from] != INF && d[e.to] > d[e.from] + e.cost) { d[e.to] = d[e.from] + e.cost; update = true; } } if (!update)break; } } bool find_negative_loop() { memset(d, 0, sizeof(d)); for (int i = 0;i < V;i++) { for (int j = 0;j < E;j++) { edge e = edges[j]; if (d[e.to] > d[e.from] + e.cost) { d[e.to] = d[e.from] + e.cost; if (i == V - 1)return true;//第V次仍然更新了 } } }return false; }