/http://blog.csdn.net/v_july_v/article/details/6057286
http://blog.163.com/cindy_19810217/
http://blog.csdn.net/v_JULY_v/article/details/6126444
/*用迪杰斯特拉算法求有向网G的V0顶点到其他顶点的最短路径P,以及其带权长度D。其中P是二维数组,行号表示终点,列号表示经过的路径。P[v][w]为TRUE的意思就是从v0到v,要经过w点)。D是一维数组,表示某顶点到v0点的路径长(D[v] == 10表示从v0到v要经过的路径长度为10。final存放已经求得的路径结果(比如final[v]为TRUE表示已经找到v0到v的最短路径)。*/
void ShorttestPath_DIJ( MGraph G, int v0, PathMatrix &P, ShortPathTable &D)
{
for( v = 0; v < G.vexnum; ++v )
{
final[v] = FALSE;
D[v] = G.arcs[v0][v];
for( w = 0; w < G.vexnum; ++w )
{
P[v][w] = FALSE;
}
if( D[v] < INFINITY )
{ //如果有直接互通的两个顶点,直接将这个路径赋值到数组P[v]。
P[v][v0] = TRUE;
P[v][v] = TRUE;
}
}
D[v0] = 0; final[v] = TRUE;
/*下面开始主循环,每次求得v0到某个v顶点的最短路径,同时刷新之前的最短路径。*/
for( i = 1; i < G.vexnum; ++i )
{ // 对于除了v0之外的顶点(这个循环仅仅限制次数,i的值不用).
min = INFINITY; // 假定初始的“最小值”为无穷大。
for( w = 0; w < G.vexnum; ++w )
{
if( !final[w] ) // w顶点在V - S中,即还未确定的顶点。
if( D[w] < min )
{
v = w;
min = D[w]; // 随着循环进行,依与v0的距离大小,从小到大取得顶点v,并标记进final。
}
}
final[v] = TRUE; // 标记已经找到
for( w = 0; w < G.vexnum; w++ )
{ // 更新路径
if( !final[w] && (min + G.arcs[v][w] < D[w]) )
{
D[w] = min + G.arcs[v][w];
P[w] = P[v]; // 把一行都给赋值了
P[w][w] = TRUE;
}
}
}
}
/*
测试数据 教科书 P189 G6 的邻接矩阵 其中 数字 1000000 代表无穷大
6
1000000 1000000 10 100000 30 100
1000000 1000000 5 1000000 1000000 1000000
1000000 1000000 1000000 50 1000000 1000000
1000000 1000000 1000000 1000000 1000000 10
1000000 1000000 1000000 20 1000000 60
1000000 1000000 1000000 1000000 1000000 1000000
结果:
D[0] D[1] D[2] D[3] D[4] D[5]
0 1000000 10 50 30 60
*/
#include <iostream>
#include <cstdio>
#define MAX 1000000
using
namespace
std;
int
arcs[10][10];
//邻接矩阵
int
D[10];
//保存最短路径长度
int
p[10][10];
//路径
int
final[10];
//若final[i] = 1则说明 顶点vi已在集合S中
int
n = 0;
//顶点个数
int
v0 = 0;
//源点
int
v,w;
void
ShortestPath_DIJ()
{
for
(v = 0; v < n; v++)
//循环 初始化
{
final[v] = 0; D[v] = arcs[v0][v];
for
(w = 0; w < n; w++) p[v][w] = 0;
//设空路径
if
(D[v] < MAX) {p[v][v0] = 1; p[v][v] = 1;}
}
D[v0] = 0; final[v0]=0;
//初始化 v0顶点属于集合S
//开始主循环 每次求得v0到某个顶点v的最短路径 并加v到集合S中
for
(
int
i = 1; i < n; i++)
{
int
min = MAX;
for
(w = 0; w < n; w++)
{
//我认为的核心过程--选点
if
(!final[w])
//如果w顶点在V-S中
{
//这个过程最终选出的点 应该是选出当前V-S中与S有关联边
//且权值最小的顶点 书上描述为 当前离V0最近的点
if
(D[w] < min) {v = w; min = D[w];}
}
}
final[v] = 1;
//选出该点后加入到合集S中
for
(w = 0; w < n; w++)
//更新当前最短路径和距离
{
/*在此循环中 v为当前刚选入集合S中的点
则以点V为中间点 考察 d0v+dvw 是否小于 D[w] 如果小于 则更新
比如加进点 3 则若要考察 D[5] 是否要更新 就 判断 d(v0-v3) + d(v3-v5) 的和是否小于D[5]
*/
if
(!final[w] && (min+arcs[v][w]<D[w]))
{
D[w] = min + arcs[v][w];
// p[w] = p[v];
p[w][w] = 1;
//p[w] = p[v] + [w]
}
}
}
}
int
main()
{
cin >> n;
for
(
int
i = 0; i < n; i++)
{
for
(
int
j = 0; j < n; j++)
{
cin >> arcs[i][j];
}
}
ShortestPath_DIJ();
for
(
int
i = 0; i < n; i++)
printf
(
"D[%d] = %d\n"
,i,D[i]);
return
0;
}