(1)BellmanFord算法能够在存在负边权值的情况下,解决单源最短路径问题,其时间复杂度为O(VE)。
算法实验思想以及算法正确性分析主要参考《算法导论》中单源最短路径一章。
(2)代码中图的实现采用邻接表,图的节点编号从0开始计数。算法输入图的结构,输出从源点到各个节点的最短距离
#include <iostream> #include <string.h> using namespace std; #define MAX_NODE 1000 #define INFINITY 9999999 #define NIL -1 typedef struct ArcNode { int adjvex;//弧指向的节点的值(点的标号) int distance;//两点之间的距离 int weight; //边的权重 ArcNode* next;//指向下一条弧 ArcNode(int value) { adjvex = value; next = NULL; } };//邻接表节点 typedef struct { int vexdata; //头节点的标号 struct ArcNode* firstarc;//第一个邻接表节点的地址 }VexNode, AdjList[MAX_NODE];//头结点 typedef struct { AdjList vexNodes; int vexNum; int arcNum;//当前节点数目和弧数 }GraphWithAL;//邻接表表示的图 //检测要输入的边是否已经存在,针对无向图 bool CheckArcIsExist(GraphWithAL* G, int v1, int v2) { ArcNode* temp = G->vexNodes[v1].firstarc; while(temp!=NULL) { if(temp->adjvex == v2) return true; temp = temp->next; } return false; } //创建图,vexNum代表顶点的个数,arcNum代表边的个数,isUnDirected代表的是 是否是无向图 void CreateGraph(GraphWithAL* G, int vexNum, int arcNum) { memset(G, 0 ,sizeof(GraphWithAL)); //初始化头结点 int i = 0; for(i=0; i<vexNum; ++i) { G->vexNum = vexNum; G->vexNodes[i].firstarc = NULL; G->vexNodes[i].vexdata = i;//从0开始计算顶点 } //初始化边 for(i=0; i<arcNum; ++i) { //输入边的顶点和尾点 int v1, v2, weight; cin>>v1>>v2>>weight; if(CheckArcIsExist(G, v1, v2)) continue; ArcNode* arcNode = new ArcNode(v2); //还需要检验边是否已经存在,这里没有检验 arcNode->next = G->vexNodes[v1].firstarc; arcNode->weight= weight; G->vexNodes[v1].firstarc = arcNode; G->arcNum++; } } void printResult(int d[], int pi[], int n) { int i=0; for(; i<n; ++i) cout<<d[i]<<" "; cout<<endl; } void InitialSingleSource(int s, int d[], int pi[], int num) { int i=0; for(; i<num; ++i) { d[i] = INFINITY; pi[i] = NIL; } d[s] = 0; } //松弛操作 void Relax(int u, int v, int weight, int d[], int pi[]) { if(d[v] > d[u]+weight) { d[v] = d[u] +weight; pi[v] = u; } } bool BellmanFord(GraphWithAL* G, int s, int d[], int pi[]) { InitialSingleSource(s, d, pi, G->vexNum); //printResult(d, pi, 5); int i = 0; ArcNode* temp = NULL; for(int j=0; j<G->vexNum-1; ++j) { for(i = 0; i<G->vexNum; ++i) { temp = G->vexNodes[i].firstarc; while(temp != NULL) { Relax(i, temp->adjvex, temp->weight, d, pi); temp = temp->next; printResult(d, pi, G->vexNum); } } } return true; } int main() { GraphWithAL G; int n, m; while(cin>>n>>m) { if(n==0) break; CreateGraph(&G, n, m); int d[5]; int pi[5]; BellmanFord(&G, 1, d, pi); printResult(d, pi, G.vexNum); } return 0; }
5 10 //图中总共有5个节点,10条边
//下面为10条边的具体信息: 源点 目标节点 权值
0 1 6
0 3 7
1 3 8
1 2 5
1 4 -4
2 1 -2
3 2 -3
3 4 9
4 2 7
4 0 2