Bellman-ford算法应对有向图中有权值为负的情况下求最短路径

来源:互联网 发布:理智与情感赏析知乎 编辑:程序博客网 时间:2024/05/16 23:57
#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();}


原创粉丝点击