首先列举一下最短路径的各种算法的运用场合。
单源最短路径:
1)dijkstra算法——无负权边,有向图、无向图
2)bellman_ford算法——负权边,但不能存在负权回路,有向图、无向图
3)Spfa算法——负权边,但不能存在负权回路,有向图、无向图
多源最短路径:
floyd算法——负权边,但不能存在负权回路,有向图、无向图
bellman_ford算法是利用松弛操作来求得最短路径,而Spfa算法是在bellman_ford算法的基础上加了队列优化,具体讲解可参考网上其它教程
下面是bellman_ford算法模型:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Max 110
#define Inf 100000010
struct Node{
int from,to;
int value;
}node[Max*Max];
int dis[Max];
int path[Max];
int n,m,num;
bool bellman_ford(int index){
for(int i=1;i<=n;i++){
path[i]=index;
dis[i]=Inf;
}
dis[index]=0;
for(int i=1;i<n;i++)
for(int j=0;j<num;j++)
if(dis[node[j].to]>dis[node[j].from]+node[j].value){
dis[node[j].to]=dis[node[j].from]+node[j].value;
path[node[j].to]=node[j].from;
}
for(int j=0;j<num;j++)
if(dis[node[j].to]>dis[node[j].from]+node[j].value)
return false;
return true;
}
void Show_path(int index){
while(true){
if(index==path[index]){
printf("%d\n",index);
break;
}
printf("%d ",index);
index=path[index];
}
}
void Show_dis(){
if(!bellman_ford(1))
printf("exist nagetive circle\n");
else{
for(int i=1;i<=n;i++)
if(dis[i]!=Inf){
printf("the shortexst length is:%d\n",dis[i]);
Show_path(i);
}
}
}
int main(){
while(scanf("%d%d",&n,&m),n){
int pivot=0;
int temp=m;
while(temp--){
scanf("%d%d%d",&node[pivot].from,&node[pivot].to,&node[pivot].value);
pivot++;
}
num=pivot;
// bellman_ford(1);
Show_dis();
}
return 0;
}
下面是Spfa算法模型:
#include <stdio.h>
#include <stdlib.h>
#include <queue>
#define Max 110
#define Inf 100000010
using namespace std;
int dis[Max];
int trim[Max][Max];
int used[Max];
bool vis[Max];
int path[Max];
int n,m;
bool spfa(int index){
queue<int> Que;
memset(vis,0,sizeof(vis));
memset(used,0,sizeof(used));
for(int i=1;i<=n;i++){
dis[i]=Inf;
path[i]=index;
}
dis[index]=0;
vis[index]=true;
used[index]=1;
Que.push(index);
while(!Que.empty()){
int point=Que.front();
Que.pop();
vis[point]=false;
for(int i=1;i<=n;i++)
if(trim[point][i]!=Inf && dis[i]>dis[point]+trim[point][i]){
dis[i]=dis[point]+trim[point][i];
path[i]=point;
if(!vis[i]){
vis[i]=true;
used[i]++;
Que.push(i);
if(used[i]>=n)
return false;
}
}
}
return true;
}
void Show_path(int index){
while(true){
if(index==path[index]){
printf("%d\n",index);
break;
}
printf("%d ",index);
index=path[index];
}
}
void Show_dis(){
if(!spfa(1))
printf("exist negative circle\n");
else{
for(int i=1;i<=n;i++)
if(dis[i]!=Inf){
printf("the shortest length is:%d\n",dis[i]);
Show_path(i);
}
}
}
int main(){
int i,j;
int a,b,value;
while(scanf("%d%d",&n,&m),n){
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
trim[i][j]=Inf;
for(i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&value);
trim[a][b]=value;
}
Show_dis();
}
return 0;
}
测试数据:
5 6
1 2 1
2 3 3
1 3 -2
4 1 2
1 5 4
3 4 -1
结果:
5 6
1 2 1
2 3 3
1 3 -2
4 1 2
1 5 4
3 4 -1
exist negative circle