#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; //边的数目
set<int>redset; //红点集合,表示已经找到最短路径的点,初始状态只有一个起始顶点
set<int>blueset; //蓝点集合,表示未找到最短路径的点,初始状态是图中除起始顶点外的所有顶点
double *Distance; //Distance表示从起始顶点到各个目标顶点的权值
int *path; //path[i]表示第i个顶点在最短路径中的父顶点
int getposofvertex(vertexType& v); //求出顶点v在图中的位置
vertexType getvertex(int i); //求出顶点i代表的元素
double getWeight(int fromvertex,int tovertex); //获取顶点fromvertex到tovertex之间的权值
void Initializationwork(vertexType& startvertex); //在求最短路径前的初始化工作
int shortestdistanceofblueset(); //在蓝点集合中查找最短距离
void adjustDistanceAndPath(int v); //依据顶点v调整Distance和path数组
void printeachpath(int i); //打印从起始顶点到顶点i的一条最短路径
public:
DirectedGraphofMatrix(int n,int m);
void showGraph() const;
void shortestpath(vertexType& startvertex); //求起始顶点到其余顶点的最短路径
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];
if(!Distance || !path) exit(0);
}
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>
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 start;
if((start=this->getposofvertex(startvertex))==-1)
{
cerr<<"图中无此顶点!"<<endl;
return;
}
this->redset.insert(start); //插入起始顶点
int i;
this->Distance[start]=0;
this->path[start]=-1;
for(i=0;i<vertexnum;i++)
{
if(this->vertex[i]!=startvertex)
{
this->blueset.insert(i); //在蓝点集合中插入其余顶点序号
this->Distance[i]=this->getWeight(start,i); //将顶点start到顶点i的权值放入Distance[i]中
if(this->Distance[i]!=MaxNumber) //顶点start到顶点i直接相连
{
this->path[i]=start;
}
else this->path[i]=-1;
}
}
}
template<class vertexType>
int DirectedGraphofMatrix<vertexType>::shortestdistanceofblueset()
{
int i,pos;
pos=-1;
double mindistance=MaxNumber;
for(i=0;i<this->vertexnum;i++)
{
if(this->blueset.count(i))
{
if(this->Distance[i]<mindistance)
{
pos=i;
mindistance=this->Distance[i];
}
}
}
return pos;
}
template<class vertexType>
void DirectedGraphofMatrix<vertexType>::adjustDistanceAndPath(int v)
{
int i;
double d;
for(i=0;i<this->vertexnum;i++)
{
if(this->blueset.count(i))
{
d=this->Distance[v]+this->getWeight(v,i);
if(d<this->Distance[i])
{
this->path[i]=v;
this->Distance[i]=d;
}
}
}
}
template<class vertexType>
void DirectedGraphofMatrix<vertexType>::shortestpath(vertexType& startvertex)
{
this->Initializationwork(startvertex);
int i;
while(!this->blueset.empty())
{
i=this->shortestdistanceofblueset(); //从蓝点集合中选择一个与起始顶点距离最近的顶点i
this->blueset.erase(i); //将顶点i从蓝点集合中删除
this->redset.insert(i); //将顶点i加入到红点集合
this->adjustDistanceAndPath(i); //依据顶点i调整数组distance和path
}
for(i=0;i<vertexnum;i++)
{
cout<<this->Distance[i]<<" ";
}
cout<<endl;
for(i=0;i<vertexnum;i++)
{
cout<<this->path[i]<<" ";
}
cout<<endl;
}
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);
g.showGraph();
char startvertex;
cout<<"请输入起始顶点:";
cin>>startvertex;
g.shortestpath(startvertex);
g.printshortestpath();
}