之前提到Dijkstra算法不能解决权值为负的情况。
{
{
queue<vertex> q;
for each vertex v in g
{
v.distance = INFINITY;
v.path = NULL;
}
s.distance = 0;
q.enqueue(s);
while (!q.Empty())
{
v = dequeue(q);
for each w adjenct to v
{
Relax(w,v)
{
if (w not in q)
q.enqueue(w);
}
}
}
}
#include <deque>
#include <algorithm>
using namespace std;
#define MAX_VERTEX_NUM 20
#define INFINITY 2147483647
struct adjVertexNode
{
int adjVertexPosition;
int weight;
adjVertexNode * next;
};
struct VertexNode
{
char data [ 2 ];
int distance;
VertexNode * path;
adjVertexNode * list;
};
struct Graph
{
VertexNode VertexNode [ MAX_VERTEX_NUM ];
int vertexNum;
int edgeNum;
};
void CreateGraph ( Graph & g)
{
int i , j , edgeStart , edgeEnd , edgeWeight;
adjVertexNode * adjNode;
cout << "Please input vertex and edge num (vnum enum):" << endl;
cin >> g . vertexNum >> g . edgeNum;
cout << "Please input vertex information (v1) /n note: every vertex info end with Enter" << endl;
for ( i = 0; i < g . vertexNum; i ++)
{
cin >> g . VertexNode [ i ]. data; // vertex data info.
g . VertexNode [ i ]. list = NULL;
}
cout << "input edge information(start end weight):" << endl;
for ( j = 0; j < g . edgeNum; j ++)
{
cin >> edgeStart >> edgeEnd >> edgeWeight;
adjNode = new adjVertexNode;
adjNode -> weight = edgeWeight;
adjNode -> adjVertexPosition = edgeEnd - 1; // because array begin from 0, so it is j-1
// 将邻接点信息插入到顶点Vi的边表头部,注意是头部!!!不是尾部。
adjNode -> next = g . VertexNode [ edgeStart - 1 ]. list;
g . VertexNode [ edgeStart - 1 ]. list = adjNode;
}
}
void PrintAdjList( const Graph & g)
{
for ( int i = 0; i < g . vertexNum; i ++)
{
cout << g . VertexNode [ i ]. data << "->";
adjVertexNode * head = g . VertexNode [ i ]. list;
if ( head == NULL)
cout << "NULL";
while ( head != NULL)
{
cout << head -> adjVertexPosition + 1 << " ";
head = head -> next;
}
cout << endl;
}
}
void DeleteGraph( Graph & g)
{
for ( int i = 0; i < g . vertexNum; i ++)
{
adjVertexNode * tmp = NULL;
while( g . VertexNode [ i ]. list != NULL)
{
tmp = g . VertexNode [ i ]. list;
g . VertexNode [ i ]. list = g . VertexNode [ i ]. list -> next;
delete tmp;
tmp = NULL;
}
}
}
void BellmanFord( Graph & g , VertexNode & s)
{
deque < VertexNode *> q;
for ( int i = 0; i < g . vertexNum; i ++)
{
g . VertexNode [ i ]. distance = INFINITY;
g . VertexNode [ i ]. path = NULL;
}
s . distance = 0;
q . push_back( &s);
int counter = 0;
while( ! q . empty())
{
VertexNode * v = q . front();
q . pop_front();
if( v == NULL)
break;
adjVertexNode * head = v -> list;
while ( head != NULL)
{
VertexNode * w = & g . VertexNode [ head -> adjVertexPosition ];
if( v -> distance + head -> weight < w -> distance)
{
w -> distance = v -> distance + head -> weight;
w -> path = v;
if ( find( q . begin (), q . end (), w) == q . end())
{
q . push_back( w);
}
}
head = head -> next;
}
counter ++;
if ( counter > g . vertexNum * g . edgeNum)
{
cout << "This graph has minus value loop!" << endl;
exit( 1);
}
}
}
void PrintPath( Graph & g , VertexNode * source , VertexNode * target)
{
if ( source != target && target -> path == NULL)
{
cout << "There is no shortest path from " << source -> data << " to " << target -> data << endl;
}
else
{
if ( target -> path != NULL)
{
PrintPath( g , source , target -> path);
cout << " ";
}
cout << target -> data ;
}
}
int main( int argc , const char ** argv)
{
Graph g;
CreateGraph( g);
PrintAdjList( g);
VertexNode & start = g . VertexNode [ 0 ];
VertexNode & end = g . VertexNode [ 6 ];
BellmanFord( g , start);
cout << "print the shortest path from v1 to v7" << endl;
PrintPath( g , & start , & end);
cout << endl;
DeleteGraph( g);
return 0;
}
if (find(q._Get_container().begin(), q._Get_container().end(), w) == q._Get_container().end())
略显臃肿。 而实际上 queue也是一个container adapter,他内部封装了deque。
运行示例:
1 含有负值权边,但不含负值回路。

运行结果

2 含有负值回路:v6->v7->v6 (-10)

运行结果

823



被折叠的 条评论
为什么被折叠?



