解决的问题依旧是找出A城市到B城市的最短路径
Bellman-Ford算法,找出各个顶点间的最短路径,路径权值可以是负数,但是不能存在负权回路(在这一回路中存在负权路径)。
而Dijkstra算法,是找出某个顶点到其它顶点的最短路径。当然Dijkstra也可以找出各个顶点间的最短路径,只要做n次Dijkstra就行了。
思路:
对每对顶点i、j,不断缩小i到j的最短路径的权。在i、j中加入顶点k,判断从i到k和k到j路径的和是否小于i到j的路径长度,如果是将k加入,并调整i到j的路径长度。
缩小的条件: a[i][j]>a[i][k]+a[k][j]; (a:每对顶点的路径长度)
下面两组测试数组,前一组没构成负权回路,后一组是负权回路,无法得出正确结果
第一组:
5
1 2 6
2 3 5
3 2 -2
5 3 -3
4 3 7
2 4 -4
5 4 9
1 5 7
4 1 2
2 5 8
0 0 0
第二组:
3
1 2 2
2 3 3
3 1 -8
0 0 0
#include<stdio.h>
#define MAX 10000
/*路径长度矩阵*/
int
a[
100
]
[
100
]
;
/*路径后继矩阵*/
int
path[
100
]
[
100
]
;
/*路径权值矩阵*/
int
c[
100
]
[
100
]
;
void
Floyd(
int
n)
{
int
i,j,k;
/*初始化a,path*/
for
(
i=
1
;
i<=
n;
++
i)
{
for
(
j=
1
;
j<=
n;
++
j)
{
if
(
c[
i]
[
j]
!
=
MAX)
{
path[
i]
[
j]
=
j;
}
else
{
path[
i]
[
j]
=
-
1
;
}
a[
i]
[
j]
=
c[
i]
[
j]
;
}
}
/*尝试将顶点k扩充到已求得的从i到j的最短路径p上*/
for
(
k=
1
;
k<=
n;
++
k)
{
for
(
i=
1
;
i<=
n;
++
i)
{
for
(
j=
1
;
j<=
n;
++
j)
{
if
(
a[
i]
[
j]
>
a[
i]
[
k]
+
a[
k]
[
j]
)
{
/*修改路径长度*/
a[
i]
[
j]
=
a[
i]
[
k]
+
a[
k]
[
j]
;
/*修改路径*/
path[
i]
[
j]
=
path[
i]
[
k]
;
}
}
}
}
}
/*判断是否是负权回路*/
int
isNegationLoop(
int
n)
{
int
i,j,k;
for
(
k=
1
;
k<=
n;
++
k)
{
for
(
i=
1
;
i<=
n;
++
i)
{
for
(
j=
1
;
j<=
n;
++
j)
{
/*如果存在顶点k,从i到j存在一条更短的路径,则构成负权回路*/
if
(
a[
i]
[
j]
>
a[
i]
[
k]
+
a[
k]
[
j]
)
{
return
0
;
}
}
}
}
return
1
;
}
/*打印各对顶点的路径情况*/
void
Print(
int
n)
{
int
i,j,next;
for
(
i=
1
;
i<=
n;
++
i)
{
for
(
j=
1
;
j<=
n;
++
j)
{
/*naxt为path的后续顶点*/
next=
path[
i]
[
j]
;
if
(
next==
-
1
)
{
printf
(
"%d - %d no path/n "
,i,j)
;
}
else
{
/*每对顶点i、j的路径长度*/
printf
(
"%d "
,a[
i]
[
j]
)
;
printf
(
"%d "
,i)
;
while
(
next!
=
j)
{
printf
(
"-> %d "
,next)
;
/*继续找下一后续顶点*/
next=
path[
next]
[
j]
;
}
printf
(
"-> %d/n "
,j)
;
}
}
}
}
int
main(
)
{
int
n,i,j,x,y,value;
scanf
(
"%d"
,&
n)
;
/*初始化c*/
for
(
i=
0
;
i<=
n;
++
i)
{
for
(
j=
0
;
j<=
n;
++
j)
{
if
(
i==
j)
{
c[
i]
[
j]
=
0
;
}
else
{
c[
i]
[
j]
=
MAX;
}
}
}
while
(
1
)
{
/*读入权值*/
scanf
(
"%d%d%d"
,&
x,&
y,&
value)
;
if
(
x==
0
&&
y==
0
&&
value==
0
)
{
break
;
}
c[
x]
[
y]
=
value;
}
Floyd(
n)
;
if
(
isNegationLoop(
n)
)
{
Print(
n)
;
}
else
{
printf
(
"the short loop isn't exit/n "
)
;
}
system
(
"pause"
)
;
return
0
;
}