图的应用
求单源最短路径
内容要点
单源最短路径可以解决类似交通旅游者的最短路径问题等,比如一个驴友要从一个城市出发到其他各个城市旅游,希望规划一个最节省费用的路线。这个问题就可以转化为图模型,用顶点表示城市,而边上的权重表示城市之间的距离(距离和费用成正比)。然后利用Dijkstra算法求一个城市到另一个两个城市之间的最短路径。
要求:
(1)给定10个城市,各个城市之间的距离,建立该图的邻接矩阵存储
(2)给定一个出发点,从该出发点利用Dijkstra算法求出一个城市到另一个城市所经过的城市序列及最短路径及长度。
代码
#include<iostream>
#include<iomanip>
using namespace std;
#define nn 10//最多10个顶点
class Graph
{
public:
char vertex[nn];//储存顶点名称的数组,假定nn个顶点
int arc[nn][nn];//储存边的二维数组
int dist[nn];//最短路径长度数组
int path[nn];//最短路径的顶点序列
int find[nn];
void creat(int n)//邻接矩阵构造有向图
{
初始化///
for(int i=0;i<n;i++)
{
arc[i][i]=999;//建立只有顶点(无边)的图
}
//填充顶点数组///
for(int i=0;i<n;i++)
{
cout<<"请输入第"<<i+1<<"个顶点名称:(char)"<<endl;
cin>>vertex[i];
arc[i][i]=0;//顶点到自己本身的边=0;
}
//填充边关系//
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
cout<<"若元素"<<vertex[i]<<"指向元素"<<vertex[j]<<"有边,则输入权值,否则输入无效值999"<<endl;
cin>>arc[i][j];
cout<<"若元素"<<vertex[j]<<"指向元素"<<vertex[i]<<"有边,则输入权值,否则输入无效值999"<<endl;
cin>>arc[j][i];
}
}
}
void show(int n)//输出有向图的信息
{
cout<<"顶点:"<<endl;
for(int i=0;i<n;i++)
cout<<vertex[i]<<' ';
cout<<endl<<endl;
cout<<"边矩阵:"<<endl;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
if(arc[i][j]<999)
cout<<setw(5)<<arc[i][j]<<' ';
else
cout<<setw(5)<<"∞"<<" ";
cout<<endl;
}
cout<<endl;
}
void DIJ(int n,int v0)//求源点v0到其他顶点的最短路径
{
//初始化
for(int i=0;i<n;i++)
{
find[i]=0;
dist[i]=arc[v0][i];//将v0到各个终点的最短路径长度初始化为边上的权值
if(dist[i]<999)
path[i]=v0;//v0和i之间有边,将i的前驱初始化为v0
else
path[i]=-1;//v0和i之间无边,i的前驱初始化为-1
}
find[v0]=1;//顶点序号为v0的进入集合S
dist[v0]=0;//源点到源点本身的权值为0
//求v0到某个顶点的最短路径
for(int i=1;i<n;i++)//对其余n-1个顶点进行计算
{
int min=999;
int v=v0;
for(int w=0;w<n;w++)//寻找最短路径
{
if(!find[w]&&dist[w]<min)
{
v=w;//选择一条当前的最短路径,终点为v
min=dist[w];
}
find[v]=1;//将v加入集合S
for(int w=0;w<n;w++)//总集合为U
{//更新从v0出发到集合U-S上所有顶点的最短路径长度
if(!find[w]&&(dist[v]+arc[v][w]<dist[w]))
{
dist[w]=dist[v]+arc[v][w];//更新G.dist[w];
path[w]=v;//更改w的前驱为v
}
}
}
}
}
void printshow(int n,int v0)//输出最短路径信息
{
char ff;int i,j,k;
int *d=new int[n];
cout<<"请输入终点名称:";
cin>>ff;cout<<endl;
/判断输入的终点是否自身///
if(ff==vertex[v0])
cout<<"到达自身的距离为0"<<endl;
/
if(ff!=vertex[v0])//如果不是顶点v0
{
//寻找顶点ff对应的编号
for(int h=0;h<n;h++)
if(vertex[h]==ff)
i=h;
//
j=i;
k=0;
while(j!=v0)
{
d[k++]=j;
j=path[j];//j=j的前驱
}
if(dist[i]<999)//存在最短路径
{
cout<<"顶点"<<vertex[v0]<<"到顶点"<<ff<<"的最短路径为:"<<vertex[v0];
while(k>0)
{
cout<<"->"<<vertex[d[--k]];
}
cout<<",最短路径长度为"<<dist[i]<<endl;
}
}
}
};
int main()
{
Graph G;
int n;int m;char c;
cout<<"请输入顶点数:";
cin>>n;cout<<n<<endl;
G.creat(n);
cout<<endl<<"图的信息如下:"<<endl;
G.show(n);
cout<<endl;
cout<<"请输入源点名称:";
cin>>c;cout<<endl;
for(int i=0;i<n;i++)
{
if(G.vertex[i]==c)
m=i;//寻找名称为c的顶点的编号
}
G.DIJ(n,m);
G.printshow(n,m);
}
自述
整理不易,可怜一下博主吧