//Dijkstra算法
//图:
/************************************************************************/
/*
16
0 1 1
0 2 5
1 2 3
1 3 7
1 4 5
2 4 1
2 5 7
3 4 2
4 5 3
3 6 3
4 6 6
4 7 9
5 7 5
6 7 2
6 8 7
7 8 4 */
/************************************************************************/
#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <set>
#include <stack>
using namespace std;
#define maxn 10
#define inf 0x3f3f3f3f //最大值
#define MAXV 9 //点的数量
int mat[MAXV][MAXV]; //矩阵图
vector<int> dis(MAXV, inf); //记录起始点到这个点的最短距离
vector<int> from(MAXV, 0); //记录路径
vector<bool> visited(MAXV, false); //标记点是否计算过
vector<vector<int> > DIS; //存储每个点的Dijkstra算法的二维向量
vector<vector<int> > FROM; //存储所有路径的二维向量
/* 节点0的最短路径 */
//void Dijkstra(){
//
// int Now;
// visited[0] = true;
// for( int v = 0 ; v < MAXV ; v ++ )
// dis[v] = mat[0][v];
//
// for( int i = 1 ; i < MAXV ; i ++ ){
//
// int minn = inf;
// for( int w = 0 ; w < MAXV ; w ++ ){
// if( !visited[w] && dis[w] < minn ){
// minn = dis[w];
// Now = w;
// }
// }
// visited[Now] = true;
// for( int w = 0 ; w < MAXV ; w ++ ){
// if( !visited[w] && dis[Now]+mat[Now][w] < dis[w] ){
// dis[w] = dis[Now]+mat[Now][w];
// from[w] = Now;
// }
// }
// }
//
//}
/* 所有点到所有点的最短路径 */
void Dijkstra() {
//当前节点
int Now;
//求所有点到所有点的最短路径
for (int count = 0; count < MAXV; count++) {
//把以count点为起始点 到其他所有点的距离先记录 假设是最短 如果没有边就是inf
for (int v = 0; v < MAXV; v++)
dis[v] = mat[count][v];
//当前点到当前点距离是0 标记true
visited[count] = true;
dis[count] = 0;
//以count为起始点 最终都会回溯到count 所以初值为count 即 每一个节点都是从count出发中间经过1个或多个节点到达
from = vector<int>(MAXV, count);
//循环n次 松弛操作
for (int i = 1; i < MAXV; i++) {
int minn = inf;
//找到起始点到这个点的最短的那个点 以这个点进行松弛操作
for (int w = 0; w < MAXV; w++) {
if (!visited[w] && dis[w] < minn) {
minn = dis[w];
Now = w;
}
}
//这句话一定要有 这个Now是已经松弛过得点 其值一定是起始点到这个点的最短距离
visited[Now] = true;
/*******************************************************/
//开始松弛操作 整个算法的核心
for (int w = 0; w < MAXV; w++) {
if (!visited[w] && dis[Now] + mat[Now][w] < dis[w]) {
dis[w] = dis[Now] + mat[Now][w];
//记录路径 从点Now到点w
from[w] = Now;
}
}
/*******************************************************/
}
vector<int> v(dis.begin(), dis.end());
DIS.push_back(v);
FROM.push_back(from);
//开始求下个点的Dijkstra 对数组进行初始化
for (int i = 0; i < MAXV; i++) {
visited[i] = false;
dis[i] = inf;
from[i] = 0;
}
}
}
void init() {
for (int i = 0; i < MAXV; i++) {
for (int j = 0; j < MAXV; j++)
mat[i][j] = inf;
}
}
void write() {
int m; //边的数量
cin >> m;
// start->end 权值为weight 有向无向都适用 唯一不同 的是无向图需要对称赋值
for (int i = 0; i < m; i++) {
int start, end, weight;
cin >> start >> end >> weight;
mat[start][end] = mat[end][start] = weight;
}
}
void printlnDis() {
for (int i = 0; i < MAXV; i++) {
printf("以节点%d为起始点:",i);
for (int j = 0; j < DIS[i].size(); j++)
cout << DIS[i][j] << " ";
cout << endl;
}
cout << endl;
}
//start为起始点的单源最短路径 找到 u -> v 的路径
void printPath(int node , int u , int w) {
cout << u << " -> " << w << " 的路径为: ";
vector<int> v(FROM[node]);
stack<int> s;
int start = u;
int end = w;
while (end != start) {
s.push(end);
end = v[end];
}
s.push(start);
while (!s.empty()) {
cout << s.top();
s.pop();
if (s.size() > 0)
cout << " -> ";
}
cout << endl;
cout << u << " -> " << w << " 的最短值为: " << DIS[u][w] << endl;
}
int main()
{
//将所有边初始化为inf
init();
//读入矩阵图
write();
//开始Dijkstra算法
Dijkstra();
//打印最短路径值
printlnDis();
//打印路径
for (int i = 0; i < MAXV; i++) {
for (int j = 0; j < MAXV; j++)
printPath(i,i,j);
cout << "************************" << endl;
}
system("pause");
return 0;
}