图(3)

图的最短路径

在有向图中,如果每条有向边都赋了权值,则称该图为赋权有向图.
求图中某顶点到其他顶点具有最小权值总和的路径,称为最短路径问题(MPL)

若将边所赋予的权值,理解为边的长度,那么最短路径问题就可以描述为:
从图中某一顶点出发,沿着图中的边,找一条到达其他顶点的路径,
使得所经过的边的总长度最小.
我们可以Dijkstra算法解决该问题.
#include<iostream>
using namespace std;
#define MaxSize 20
#define inf  2147483647
struct Graph{
	int V[MaxSize];          //存储顶点的数组 
	int M[MaxSize][MaxSize]; //存储边的数组 
	int n;					 //图所含顶点个数 
}; 
//根据顶点集V 边集合E 创建图的领接矩阵 
void Create(Graph &G,int *V,int vn,int *E,int en,int action){
	int i,j,k,w;
	G.n=vn;
	for(i=0;i<G.n;i++)
		G.V[i]=V[i];
		
	for(i=0;i<G.n;i++){
		for(j=0;j<G.n;j++)
			if(i==j)
				G.M[i][j]=0;
			else
				G.M[i][j]=inf;	
	}
	
	for(k=0;k<en;k++){
		i=E[3*k+0];
		j=E[3*k+1];
		w=E[3*k+2];
		G.M[i][j]=w;
		if(action==0) //如果是无向图 
			G.M[j][i]=w;
	}	
}
//输出邻接矩阵
void Display1(Graph G){
	int i,j; 
	cout<<"顶点"<<"\t";
	for(i=0;i<G.n;i++)
		cout<<"V"<<G.V[i]<<"\t";
	cout<<endl;
	for(i=0;i<G.n;i++){
		cout<<"V"<<G.V[i]<<"\t";
		for(j=0;j<G.n;j++)
			if(G.M[i][j]==inf)
				cout<<"inf"<<"\t";
			else
				cout<<G.M[i][j]<<"\t";	
		cout<<endl;	
	}
} 
//Dijkstra算法
void MPL(Graph G,int U[],int dist[],int path[],int sv){
	int i,j,k,min;
	//对U,dist,path初始化 
	for(j=0;j<G.n;j++){
		dist[j]=G.M[sv][j];					//顶点sv到j的距离 
		if(j==sv) U[j]=1;					//sv进入集合U 
		else U[j]=0;
		if(G.M[sv][j]!=inf) path[j]=sv;		//顶点j与sv连通 
		else path[j]=-1;					//或不连通 
	}
	for(i=0;i<G.n;i++){				//U中仅加入顶点sv,还需再加入G.n-1个顶点 
		min=inf;
		k=-1;
		for(j=0;j<G.n;j++)			//顺序搜索不在U中的顶点Jj,且到顶点sv的距离最小者 
			if(U[j]==0&&dist[j]<min){
				k=j;				//记录顶点号 
				min=dist[j];		//更改最短距离 
			}
		U[k]=1;	 					//顶点k加入U
		//由于顶点k加入U,需修改不在U中顶点j到sv的距离 
		for(j=0;j<G.n;j++){
			if(U[j]==0)
				if(G.M[k][j]<inf&&dist[k]+G.M[k][j]<dist[j]){
					dist[j]=dist[k]+G.M[k][j];
					path[j]=k;     //顶点k称为顶点j的前驱 
				} 
		} 
	} 
} 
//输出从起点sv到终点ev的最短距离与最短路径(递归方式)
void Display(int dist[],int path[],int sv,int ev){
	if(path[ev]==-1){
		cout<<"没有从起点"<<sv<<"到终点"<<ev<<"的路径"<<endl;
		return; 
	}
	if(path[ev]==ev)
		cout<<"V"<<ev;
	else{
		Display(dist,path,sv,path[ev]);
		cout<<"=>V"<<ev;
	}
} 
 
int main(){
	int V[5]={0,1,2,3,4};
	int E[7][3]={{0,1,3},{0,2,4},{1,2,6},{2,3,1},{2,4,7},{3,0,5},{3,4,2}};
	Graph G;
	Create(G,&V[0],5,&E[0][0],7,1);
	cout<<"图的领接矩阵"<<endl;
	Display1(G);
	int sv=0;
	int U[MaxSize],dist[MaxSize],path[MaxSize];
	MPL(G,U,dist,path,sv);
	for(int i=0;i<G.n;i++){
		cout<<"V"<<sv<<"=>V"<<i<<"最短路径长度:"<<dist[i]<<endl;
		cout<<"最短路径:";
		Display(dist,path,sv,i);
		cout<<endl; 	 
	} 	
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值