#include<iostream>
#include<vector>
#include<set>
#include<stack>
#include<stdlib.h>
using namespace std;
const int MaxNumber=1e10;
struct EdgeType //边的类型
{
int fromvertex; //边的起点
int tovertex; //边的终点
double weight; //边上的权值
};
template<class vertexType>
class DirectedGraphofMatrix //邻接矩阵存储的有向图
{
private:
vector<vertexType>vertex; //顶点向量
int vertexnum; //顶点数目
vector<EdgeType>edge; //边向量
int edgenum; //边的数目
double *Distance; //Distance表示从起始顶点到各个目标顶点的权值
int *path; //path[i]表示第i个顶点在最短路径中的父顶点
int *indegree; //顶点的入度
int sourcevertex; //源点
bool *Changed; //Changed[i]==false表示Distance[i]没有被更新,否则,表示Distance[i]被更新
int getposofvertex(vertexType& v); //求出顶点v在图中的位置
vertexType getvertex(int i); //求出顶点i代表的元素
double getWeight(int fromvertex,int tovertex); //获取顶点fromvertex到tovertex之间的权值
void SetChanged(); //将Changed都设置为false
bool CheckChanged(); //检查Changed是不是都是false
void UpdateEdge(EdgeType& e); //更新边,更新Distance,path,Changed
void printeachpath(int i); //打印从起始顶点到顶点i的一条最短路径
public:
DirectedGraphofMatrix(int n,int m);
void TopSort(); //拓扑排序
void Initializationwork(vertexType& startvertex); //在求最短路径前的初始化工作
void LoopAdjustEdge(); //循环调整边
void showGraph() const;
void printshortestpath(); //打印从起始顶点到其余顶点的最短路径
};
bool checkInputFormat(istream& is) //检查输入格式是否正确
{
if(!is.good())
{
cerr<<" 输入格式错误!"<<endl;
return false;
}
else return true;
}
template<class vertexType>
DirectedGraphofMatrix<vertexType>::DirectedGraphofMatrix(int n=0,int m=0):vertexnum(n),edgenum(m)
{
int i;
vertexType v;
EdgeType e;
for(i=0;i<n;i++)
{
cout<<"请输入第"<<i<<"个顶点:";
cin>>v;
if(!checkInputFormat(cin)) return;
else this->vertex.push_back(v);
}
for(i=0;i<m;i++)
{
cout<<" 请输入第"<<i<<"条边的起点:";
cin>>e.fromvertex;
cout<<" 请输入第"<<i<<"条边的终点:";
cin>>e.tovertex;
cout<<" 请输入第"<<i<<"条边的权值:";
cin>>e.weight;
this->edge.push_back(e);
}
Distance=new double[vertexnum];
path=new int[vertexnum];
this->indegree=new int[vertexnum];
this->Changed=new bool[vertexnum];
if(!Distance || !path || !indegree || !Changed) exit(0);
}
template<class vertexType>
void DirectedGraphofMatrix<vertexType>::TopSort()
{
stack<int>vertex_stack; //保存入度为0的顶点序号
int n=0; //拓扑排序中得顶点数目
int i,j,k;
for(i=0;i<this->vertexnum;i++)
{
if(this->indegree[i]==0)
{
vertex_stack.push(i); //将第i个顶点入栈
n++;
}
}
while(vertex_stack.empty()==false)
{
i=vertex_stack.top();
vertex_stack.pop();
for(k=0;k<this->edgenum;k++)
{
if(this->edge[k].fromvertex==i)
{
j=this->edge[k].tovertex;
this->indegree[j]--;
if(this->indegree[j]==0) //第j个顶点入度为0
{
vertex_stack.push(j);
n++;
}
}
}
}
if(n!=vertexnum)
{
cerr<<" 有向图中存在环路!"<<endl;
exit(0);
}
}
template<class vertexType>
void DirectedGraphofMatrix<vertexType>::UpdateEdge(EdgeType& e)
{
int i,j;
i=e.fromvertex;
j=e.tovertex;
if(this->Distance[i]+this->getWeight(i,j)<this->Distance[j])
{
this->Distance[j]=this->Distance[i]+this->getWeight(i,j); //更新Distance[j]
this->path[j]=i; //更新path[j],i是j的最短路径上的父节点
this->Changed[j]=true; //表明第j个顶点的Distance已经改变
}
}
template<class vertexType>
void DirectedGraphofMatrix<vertexType>::LoopAdjustEdge()
{
int i;
do
{
for(i=0;i<edgenum;i++) //对所有边进行调整
{
this->UpdateEdge(this->edge[i]);
}
if(this->CheckChanged()==true) return; //一轮调整后Changed未发生改变,边更新完毕
this->SetChanged(); //否则将Changed都置为false,进行下一轮调整
}while(true);
}
template<class vertexType>
void DirectedGraphofMatrix<vertexType>::showGraph() const
{
int i;
for(i=0;i<this->vertexnum;i++)
{
cout<<" 第"<<i<<"个顶点是:"<<this->vertex[i]<<endl;
}
for(i=0;i<this->edgenum;i++)
{
cout<<" 第"<<i<<"条边的起点是:"<<this->edge[i].fromvertex<<endl;
cout<<" 第"<<i<<"条边的终点是:"<<this->edge[i].tovertex<<endl;
cout<<" 第"<<i<<"条边的权值是:"<<this->edge[i].weight<<endl;
}
}
template<class vertexType>
int DirectedGraphofMatrix<vertexType>::getposofvertex(vertexType& v)
{
int i;
for(i=0;i<this->vertexnum;i++)
{
if(v==this->vertex[i]) return i;
}
return -1;
}
template<class vertexType>
void DirectedGraphofMatrix<vertexType>::SetChanged()
{
int i;
for(i=0;i<vertexnum;i++) this->Changed[i]=false;
}
template<class vertexType>
bool DirectedGraphofMatrix<vertexType>::CheckChanged() //Changed元素都是false,函数返回true
{
int i;
for(i=0;i<vertexnum;i++)
{
if(this->Changed[i]==true) return false;
}
return true;
}
template<class vertexType>
vertexType DirectedGraphofMatrix<vertexType>::getvertex(int i)
{
int j;
for(j=0;j<vertexnum;j++)
{
if(i==j) return this->vertex[i];
}
}
template<class vertexType>
double DirectedGraphofMatrix<vertexType>::getWeight(int fromvertex,int tovertex)
{
int i;
for(i=0;i<edgenum;i++)
{
if(this->edge[i].fromvertex==fromvertex && this->edge[i].tovertex==tovertex)
{
return this->edge[i].weight;
}
}
return MaxNumber;
}
template<class vertexType>
void DirectedGraphofMatrix<vertexType>::Initializationwork(vertexType& startvertex) //在求最短路径前的初始化工作
{
int i;
sourcevertex=this->getposofvertex(startvertex); //获取源点序号
if(sourcevertex==-1)
{
cerr<<"输入的源点不存在,程序终止!"<<endl;
exit(0);
}
for(i=0;i<this->vertexnum;i++)
{
this->indegree[i]=0; //将所有顶点入度清零
this->Changed[i]=false; //初始时所有Changed[i]都为false;
}
for(i=0;i<this->edgenum;i++)
{
this->indegree[this->edge[i].tovertex]++; //统计所有顶点入度
}
this->Distance[sourcevertex]=0;
for(i=0;i<vertexnum;i++)
{
if(i!=sourcevertex) this->Distance[i]=MaxNumber;
this->path[i]=-1;
}
}
template<class vertexType>
void DirectedGraphofMatrix<vertexType>::printeachpath(int i)
{
int parent; //parent是当前顶点的父顶点
double d=this->Distance[i]; //d是起始顶点到顶点i的最短路径长度
stack<int>s; //栈s用于保存最短路径上的顶点
cout<<" 起始顶点到顶点"<<this->getvertex(i)<<"的最短路径是:";
while((parent=this->path[i])!=-1) //顶点i有父顶点
{
s.push(parent);
i=parent;
}
while(!s.empty())
{
cout<<this->getvertex(s.top())<<" ";
s.pop();
}
cout<<d<<endl;
}
template<class vertexType>
void DirectedGraphofMatrix<vertexType>::printshortestpath()
{
int i;
for(i=0;i<vertexnum;i++)
{
this->printeachpath(i);
}
}
void main()
{
int n,m;
cout<<"请输入顶点个数:";
cin>>n;
cout<<" 请输入边的个数:";
cin>>m;
DirectedGraphofMatrix<char>g(n,m);
char sourcevertex;
cout<<"请输入源点:";
cin>>sourcevertex;
g.Initializationwork(sourcevertex);
g.showGraph();
g.TopSort();
g.LoopAdjustEdge();
g.printshortestpath();
}
Bellman-ford算法应对有向图中有权值为负的情况下求最短路径
原文作者:Bellman - ford算法
原文地址: https://blog.csdn.net/wangzhicheng1983/article/details/7650703
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/wangzhicheng1983/article/details/7650703
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。