图--单源最短路径 -Bellman Ford 算法(可以存在负权边的情况和负权回路)算法导论p362

来源:互联网 发布:java异常机制 编辑:程序博客网 时间:2024/05/17 21:45

 Bellman Ford 算法  可以存在负权边的情况下解决单源最短路问题和,当出现负权回路时返回布尔值0,不然,则返回1,并可以源点到各点输出最短路径

主要步骤:

1、建立图(连接矩阵);

2、运行Bellman Ford 算法:

            对各点初始化;

           对图中的每一条边进行先后松弛n-1次

           检测是否有回路:当出现d[v]>d[u]+w(u,v)时即存在负权回路

3、输出结果

#include<stdio.h>#define MAX 1000000#define maxsize 10001int G[maxsize][maxsize];typedef struct{char ch; //节点字符int pre;//前驱int d; //距离}Node;Node V[maxsize];void input(int n,int e)//节点和边的录入 及建立连接矩阵图G{int i,j,find,weight,s,d;char ch1,ch2;printf("请输入图的顶点 第一个顶点默认为源点\n");for(i=0;i<n;i++)scanf("%c ",&V[i].ch);for(i=0;i<=n;i++)for(j=0;j<=n;j++)G[i][j]=MAX;for(i=1;i<=e;i++){scanf("%c %c %d ",&ch1,&ch2,&weight);find=0;for(j=0;find<2&&j<n;j++)if(ch1==V[j].ch){s=j;find++;}else if(ch2==V[j].ch){d=j;find++;}    G[s][d]=weight;}}void INTIALIZE_SINGLE_SOURCE(int n)//各节点最短距离和前驱的初始化{int i;for(i=0;i<n;i++){V[i].d=MAX;V[i].pre=-1;}V[0].d=0;}void RELAX(int u,int v)//松弛{if(V[v].d>V[u].d+G[u][v]){V[v].d=V[u].d+G[u][v];V[v].pre=u;}}int BELLMAN_FORD(int n)//BELLman ford 算法{  int u,v,k;INTIALIZE_SINGLE_SOURCE(n);for(k=1;k<n;k++)   //对每条边都要松弛n-1次for(u=0;u<n;u++)for(v=0;v<n;v++)if(G[u][v]<MAX)RELAX(u,v);for(u=0;u<n;u++)//判断图中是否有负权回路for(v=0;v<n;v++)if(V[v].d>V[u].d+G[u][v])return 0;           //有回路返回布尔值0return 1;//没回路返回布尔值1}void printpath(int i)//路径输出{if(V[i].pre==-1){printf("%c->",V[i].ch);return ;}else{    printpath(V[i].pre);printf("-%c",V[i].ch);}}void print(int n,int flag)//输出{int i;if(flag==0)printf("有回路\n");else{for(i=0;i<n;i++)if(V[i].pre!=-1){printf("%d: ",V[i].d);printpath(i);printf("\n");}else if(i==0)printf("%d %c\n",V[i].d,V[i].ch);elseprintf(" 无穷大 %c\n",V[i].ch);}}int main(){   freopen("1.txt","r",stdin);int n,e,flag;printf("请输入图的顶点的个数n和边数e:\n");scanf("%d%d ",&n,&e);input(n,e);    //节点和边的录入 及建立连接矩阵图Gflag=BELLMAN_FORD(n);  //BELLman ford 算法 有回路返回布尔值0,没回路返回布尔值1print(n,flag);//输出return 0;}

测试数据

5 10
s t x y z
s t 6
s y 7
t y 8
t x 5
t z -4
y x -3
y z 9
z x 7
z s 2
x t -2
 

原创粉丝点击