单源最短路径Bellman_Ford算法C++实现

2021年5月4日 4点热度 0条评论 来源: 一只鸟的天空

// 单源最短路径Bellman_Ford算法.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<iostream>
#define MAX 100
#define Infinity 65535
typedef int WeiType;
using namespace std;

 

struct edgeNode
{
 int no; //边尾端的序号
 char info; //边端的名称
 WeiType weight; //边权值
 struct edgeNode * next; //下一个
};

 

struct vexNode
{
 char info;  //节点名称
 struct edgeNode *link; //与之相连的端点
};

//存储节点信息
vexNode adjlist[MAX];
//前驱节点
int parent[MAX];
//源点到节点j最短路径的花费
WeiType lowcost[MAX];

//建立邻接表存储
//adjlist为节点集,n为节点个数,e为边数目
//返回源点序号
int createGraph(vexNode *adjlist,int n,int e)
{
 int i;
 for(i=1;i<=n;i++)
 {
  cout<<"请输入节点"<<i<<"的名称:";
  cin>>adjlist[i].info;
  adjlist[i].link = NULL;
  parent[i] = i;
  lowcost[i] = Infinity;
 }
 edgeNode *p1;
   int v1,v2;
   WeiType weight;
 for(i=1;i<=e;i++)
 {
  cout<<"请输入边"<<i<<"的起始节点与尾节点序号:";
  cin>>v1>>v2;
  cout<<"请输入此边的权值:";
  cin>>weight;
  p1 = (edgeNode*)malloc(sizeof(edgeNode));
  p1->no = v2;
  p1->weight = weight;
  p1->info = adjlist[v2].info;
  p1->next = adjlist[v1].link;
  adjlist[v1].link = p1;
 }
 cout<<"请输入源点序号:";
 int v0;
 cin>>v0;
 lowcost[v0] = 0;
 return v0;
}

/*
//
void relax(WeiType *lowcost,int *parent,const int u,const int v,const WeiType w)
{
 if(lowcost[v]>lowcost[u]+w)
 {
  lowcost[v] = lowcost[u] + w;
  parent[v] = u;
 }
}
*/
//
bool Bellman_Ford(vexNode *adjlist,WeiType *lowcost,int *parent,const int n)
{
 int i,j;
 for(j=1;j<n;j++)
 {
  for(i=1;i<=n;i++)
  {
   edgeNode *p1 = adjlist[i].link;
   while(p1 != NULL)
   {
    if(lowcost[i]+p1->weight <lowcost[p1->no])
    {
     lowcost[p1->no] = lowcost[i]+p1->weight;
     parent[p1->no] = i;
    }
    p1 = p1->next;
   }
  }
 }
 //检查有无负回路
  for(i=1;i<=n;i++)
  {
   edgeNode *p2 = adjlist[i].link;
   while(p2 != NULL)
   {
    if(lowcost[p2->no]>lowcost[i]+p2->weight)
     return false;
    p2 = p2->next;
   }
  }
 return true;
}

//打印源点到节点i最短路径
void print_it(vexNode *adjlist,int *parent,const int v0,const int i)
{
 if(i == v0)
  cout<<"("<<v0<<":"<<adjlist[v0].info<<")  ";
 else
 {
  print_it(adjlist,parent,v0,parent[i]);
  cout<<"("<<i<<":"<<adjlist[i].info<<")  ";
 }
}

int _tmain(int argc, _TCHAR* argv[])
{
 int cases;
 cout<<"请输入案例的个数:";
 cin>>cases;
 while(cases--)
 {
  int n,e;
  cout<<"请输入节点数:";
  cin>>n;
  cout<<"请输入边数:";
  cin>>e;
  //创建邻接表
  int v0 = createGraph(adjlist,n,e);
  //调用Bellman-Ford算法
  bool flag = Bellman_Ford(adjlist,lowcost,parent,n);
  int i;
  //输出源点到其余每一点的最短路径(节点序号:节点名称)
  for(i=1;i<=n;i++)
  {
   cout<<"从源点"<<adjlist[v0].info<<"到点"<<adjlist[i].info<<"的路径为:"<<endl;
   print_it(adjlist,parent,v0,i);
     cout<<endl;
   cout<<"此路径花费为:"<<lowcost[i]<<endl;
 
  }
 }
 system("pause");
 return 0;
}

--------------------------------------------------------程序测试--------------------------------------------------------

                                                            

请输入案例的个数:1
请输入节点数:5
请输入边数:10
请输入节点1的名称:s
请输入节点2的名称:t
请输入节点3的名称:x
请输入节点4的名称:y
请输入节点5的名称:z
请输入边1的起始节点与尾节点序号:1 2
请输入此边的权值:6
请输入边2的起始节点与尾节点序号:1 4
请输入此边的权值:7
请输入边3的起始节点与尾节点序号:2 3
请输入此边的权值:5
请输入边4的起始节点与尾节点序号:2 4
请输入此边的权值:8
请输入边5的起始节点与尾节点序号:2 5
请输入此边的权值:-4
请输入边6的起始节点与尾节点序号:3 2
请输入此边的权值:-2
请输入边7的起始节点与尾节点序号:4 3
请输入此边的权值:-3
请输入边8的起始节点与尾节点序号:4 5
请输入此边的权值:9
请输入边9的起始节点与尾节点序号:5 1
请输入此边的权值:2
请输入边10的起始节点与尾节点序号:5 3
请输入此边的权值:7
请输入源点序号:1
从源点s到点s的路径为:
(1:s)
此路径花费为:0
从源点s到点t的路径为:
(1:s)  (4:y)  (3:x)  (2:t)
此路径花费为:2
从源点s到点x的路径为:
(1:s)  (4:y)  (3:x)
此路径花费为:4
从源点s到点y的路径为:
(1:s)  (4:y)
此路径花费为:7
从源点s到点z的路径为:
(1:s)  (4:y)  (3:x)  (2:t)  (5:z)
此路径花费为:-2
请按任意键继续. . .

    原文作者:一只鸟的天空
    原文地址: https://blog.csdn.net/heyongluoyao8/article/details/6954111
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。