Posted on 2009-04-09 10:45
lzmagic 閱讀(6203)
評論(3) 編輯 收藏 引用 所屬分類:
Algorithm

/**//**
* DIJKSTRA(簡單版) 單源最短路徑算法(不允許存在負(fù)邊)
* 輸入:(1)圖g; // 有向圖或者無向圖
* (2)源點s。
* 輸出:(1)源點s到各點的最短路徑長dist;
* (2)源點s到各點的最短路徑prev。
* 結(jié)構(gòu): 圖g用鄰接矩陣表示,最短路徑長dist用數(shù)組表示。
* 算法:Dijkstra算法
* 復(fù)雜度:O(|V|^2)
*/
#include <iostream>
#include <vector>
#include <list>
#include <iterator>
#include <algorithm>
#include <numeric>
#include <functional>
#include <climits>
using namespace std;

int n; // n : 頂點個數(shù)
vector<vector<int> > g; // g : 圖(graph)(用鄰接矩陣(adjacent matrix)表示)
int s; // s : 源點(source)
vector<bool> known; // known : 各點是否知道最短路徑
vector<int> dist; // dist : 源點s到各點的最短路徑長
vector<int> prev; // prev : 各點最短路徑的前一頂點

void Dijkstra() // 貪心算法(Greedy Algorithm)


{
known.assign(n, false);
dist.assign(n, INT_MAX);
prev.resize(n); // 初始化known、dist、prev。
dist[s] = 0; // 初始化源點s到自身的路徑長為0。
for (;;)

{
int min = INT_MAX, v = s;
for (int i = 0; i < n; ++i)
if (!known[i] && min > dist[i])
min = dist[i], v = i; // 尋找未知的最短路徑長的頂點v,
if (min == INT_MAX) break; // 如果找不到,退出;
known[v] = true; // 如果找到,將頂點v設(shè)為已知,
for (int w = 0; w < n; ++w) // 遍歷所有v指向的頂點w,
if (!known[w] && g[v][w] < INT_MAX && dist[w] > dist[v] + g[v][w])
dist[w] = dist[v] + g[v][w], prev[w] = v; // 調(diào)整頂點w的最短路徑長dist和最短路徑的前一頂點 prev。
}
}

void Print_SP(int v)


{
if (v != s) Print_SP(prev[v]);
cout << v << " ";
}

int main()


{
n = 7;
g.assign(n, vector<int>(n, INT_MAX));
g[0][1] = 2; g[0][3] = 1;
g[1][3] = 3; g[1][4] = 10;
g[2][0] = 4; g[2][5] = 5;
g[3][2] = 2; g[3][4] = 2; g[3][5] = 8; g[3][6] = 4;
g[4][6] = 6;
g[6][5] = 1;
s = 0;
Dijkstra();
copy(dist.begin(), dist.end(), ostream_iterator<int>(cout, " ")); cout << endl;
for (int i = 0; i < n; ++i)
if(dist[i] != INT_MAX)

{
cout << s << "->" << i << ": ";
Print_SP(i);
cout << endl;
}
system("pause");
return 0;
}
