第十届蓝桥杯C/C++研究生组D题

最短路

问题描述

如下图所示,G是一个无向图,其中蓝色边的长度是1,橘色边的长度是2,绿色边的长度是3,计算从A到S的最短距离是多少?
在这里插入图片描述

思路

这个题是最短路径问题。简单的思路就是,一个数组,存储两点之间的距离,然后定义一个数组记录始点到终点的最短距离。例如:A->E,A->D,A->C,A->B,存储之间的距离,为1,1,1,2;然后E->I,E->D,E->H,D->I,D->H,D->G,D->E,D->C······距离分别为3,1,1,1,2,1,2,1,2·····依次存储,得出A->S的最短距离并输出。

代码如下

#include <stdio.h>

#define max  100000 //表示两点之间没有连通
#define Vertex 20 //表示图的顶点 

//定义图 
typedef struct{
	int vertexNum;  
    char vertex[Vertex];  
    int arc[Vertex][Vertex];
}Graph,*PGraph;
//辅助数组
typedef struct{
	int distance;
	int path[Vertex];
}ArrayNode; 
//构造图 
void createGraph(PGraph G){
	int i,j;
	G->vertexNum=19;
	for(i=0;i<G->vertexNum;i++){
		G->vertex[i]='A'+1;
	}
	for(i=0;i<G->vertexNum;i++)
		for(j=0;j<G->vertexNum;j++)
			G->arc[i][j] = 0;
	G->arc[0][1]=2;
	G->arc[0][2]=1;
	G->arc[0][3]=1;
	G->arc[0][4]=1;
	G->arc[1][0]=2;
	G->arc[1][6]=1;
	G->arc[1][9]=2;
	G->arc[2][0]=1;
	G->arc[2][3]=3;
	G->arc[2][5]=3;
	G->arc[3][0]=1;
	G->arc[3][2]=3;
	G->arc[3][4]=1;
	G->arc[3][6]=2;
	G->arc[3][7]=1;
	G->arc[3][8]=2;
	G->arc[4][0]=1;
	G->arc[4][3]=1;
	G->arc[4][7]=1;
	G->arc[4][8]=3;
	G->arc[5][2]=3;
	G->arc[5][6]=1;
	G->arc[5][9]=1;
	G->arc[6][2]=3;
	G->arc[6][3]=2;
	G->arc[6][1]=1;
	G->arc[6][5]=1;
	G->arc[6][8]=3;
	G->arc[7][3]=1;
	G->arc[7][4]=1;
	G->arc[7][8]=1;
	G->arc[7][11]=2;
	G->arc[8][7]=1;
	G->arc[8][6]=3;
	G->arc[8][4]=3;
	G->arc[8][12]=3;
	G->arc[9][2]=2;	
	G->arc[9][5]=1;
	G->arc[9][18]=2;
	G->arc[10][13]=1;
	G->arc[10][16]=2;
	G->arc[10][11]=3;
	G->arc[10][6]=2;
	G->arc[11][12]=1;
	G->arc[11][17]=1;
	G->arc[11][7]=2;
	G->arc[11][10]=3;
	G->arc[12][18]=1;
	G->arc[12][15]=1;
	G->arc[12][13]=2;
	G->arc[12][11]=1;
	G->arc[12][8]=3;
	G->arc[13][16]=1;
	G->arc[13][12]=2;
	G->arc[13][10]=1;
	G->arc[14][16]=1;
	G->arc[14][17]=3;
	G->arc[14][15]=1;
	G->arc[15][14]=1;
	G->arc[15][13]=1;
	G->arc[16][13]=1;
	G->arc[16][10]=2;
	G->arc[16][14]=1;
	G->arc[17][14]=3;
	G->arc[17][11]=1;
	G->arc[17][18]=1;
	G->arc[18][17]=1;
	G->arc[18][12]=1;
	G->arc[18][9]=2;
}
void Dijstra(PGraph G,int from,int to){
	//printf("ceshi"); 
	int i,j,index=-1;
	int n=1;//记录最短路径的个数 
	ArrayNode shortpath[Vertex];
	int flag[Vertex]={0};//标记,代表到这个顶点的距离已求出
	//初始化shortpath数组 
	for(i=0;i<G->vertexNum;i++){
		if(from==i){
			shortpath[i].distance = 0;
			shortpath[i].path[0]=i;
			flag[from]=i; 
		}else if(G->arc[from][i]>0){
			shortpath[i].path[0]=from;
			shortpath[i].path[1]=i;
			shortpath[i].distance=G->arc[from][i];
		}else{
			shortpath[i].distance=max;
		}
	}
	//每次求出一个最短路径
	while(n<G->vertexNum){
		index=-1;//标记点 
		for(i=0;i<G->vertexNum;i++){
			if(i==from){
				continue;//若为自身,跳出 
			}
			if(flag[i]==0&&index==-1&&shortpath[i].distance!=max){
				index = i;
			}if(flag[i]==0&&index!=-1&&shortpath[i].distance<shortpath[index].distance){
				index = i;//标记最短路径点 
			}
		}
		flag[index]=1;
		//修改到各个顶点的最短路径
		for(i=0;i<G->vertexNum;i++){
			if(i==from){
				continue;
			}
			if(G->arc[index][i]>0 && G->arc[index][i]+shortpath[index].distance<shortpath[i].distance){
				shortpath[i].distance=G->arc[index][i]+shortpath[index].distance;
				//修改路径
				j=0;
				while(1){
					shortpath[i].path[j]=shortpath[index].path[j];
					if(shortpath[index].path[j]==index){
						break;
					}
					j++;
				}
				shortpath[i].path[j+1]=i;
			}
		} 
		n++;
	} 
	//输出from到to的最短路径及长度
	if(shortpath[to].distance==max){
		printf("%c到%c没有路径",from+'A',to+'A');
		return;
	} 
	printf("从%c到%c的最短路径是:%d\n",from+'A',to+'A',shortpath[to].distance);
	printf("经过的顶点:  ");
	i=0;
	while(1){
		printf("%-3c",shortpath[to].path[i]+'A');
		if(shortpath[to].path[i]==to){
			break;
		}
		i++;
	} 
	printf("\n");
}
int main(){
	Graph g;
	char from,to;
	createGraph(&g);
	scanf("%c%c",&from,&to);//输入始点与终点 
	Dijstra(&g,from-'A',to-'A');
} 

结果图

在这里插入图片描述
代码参考链接

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值