上机五:图的应用——单源最短路径

图的应用

求单源最短路径

内容要点

单源最短路径可以解决类似交通旅游者的最短路径问题等,比如一个驴友要从一个城市出发到其他各个城市旅游,希望规划一个最节省费用的路线。这个问题就可以转化为图模型,用顶点表示城市,而边上的权重表示城市之间的距离(距离和费用成正比)。然后利用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);
}

自述

整理不易,可怜一下博主吧

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纸梯先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值