首先列舉一下最短路徑的各種算法的運用場合。
單源最短路徑:
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