图论-最短路-迪杰斯特拉算法

在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? 
 

Input

输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。 
输入保证至少存在1条商店到赛场的路线。 

Output

对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间

Sample Input

2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0

Sample Output

3
2

显然,本题是最短路问题,但是没有权值,为基础题;

运用迪杰斯特拉算法,

迪杰斯特拉算法是求出图中某一点到任意点的最短路径,下面是迪杰斯特拉算法的函数代码

const int INF = 0x3f3f3f3f;
const int MAXN = 10;
int dist[MAXN];

int edge[MAXN][MAXN];

void Dijkstra(int start){
	bool S[MAXN];                                  // 判断是否已存入该点到S集合中
	int n = MAXN;
	// 初始化 
	for(int i = 1; i <= n; ++i){
		dist[i] = edge[start][i];					//dist存放的是各边与源点的距离
		S[i] = false;                                // 初始都未用过该点
	}
	dist[start] = 0;
	S[start] = true;
	// S中现有一个点,U中有n - 1个,每次循环将U中一个点添加到S中
	// 所以需要n - 1次循环 
	// 时间复杂度O(n^2) 
	for(int i = 2; i <= n; i++){ 
		int mindist = INF;
		int v = start;
		// 找出U中距离起点start最近的点v 
		for(int j = 1; j <= n; ++j){
			if((!S[j]) && dist[j] < mindist){		
				v = j;                             // u保存当前邻接点中距离最小的点的号码 
				mindist = dist[j];
			}
		}											//找出一个与远点最近的点, 
		// 把最近的这个点v添加到S中 
		S[v] = true; 
		// 更新与v相邻顶点的最短距离 
		for(int j = 1; j <= n; j++){					//通过循环来找出各点的距离 
			if((!S[j]) && edge[v][j] < INF){
				if(dist[v] + edge[v][j] < dist[j]){     //在通过新加入的u点路径找到离start点更短的路径  
					dist[j] = dist[v] + edge[v][j];    //更新dist 
				}
	    	}
	    }
	}
}

我提交了四边才AC,在这里说明一下自己的认为的重点;

1、在主函数中edge是一个存放两点间是否有路径的长度,在初始化该数组的时候,需要初始化为最大值;

2、dist是存放源点与某一点间的距离,也需要初始化最大值,而后赋值为【源点与该点是否有直接路径】,再通过循环求出每一点与源点的路径距离(最短);

3、接下来是最大的for循环,每次都只是向该bool添加一个点,共需要n-1次循环,

4、for1循环是找出与源点距离最近的点,在大for第一次中找的是直接点,而后的点便是累加的最短距离点

5、for2循环是通过for1循环找出的点,与已知点的最短距离,并为该点的dist赋值,方便下一次循环

理解之后,便开始手撸代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string.h> 
#include<queue>
using namespace std; 
int dist[110],edge[110][110],n,m,INF=0x3f3f3f3f;
bool s[110];
 
int  dij(int start)
{
	for(int i=1;i<=n;i++){
		s[i]=false;
		if(edge[start][i]>0) { 
		dist[i]=edge[start][i];} 
		else dist[i] = INF; 
	
	} 
	s[start]=true;  
	dist[start]=0; 
	for(int i=2;i<=n;i++){
		int v=start,mindist=INF; 
		for(int j=1;j<=n;j++){
			if((!s[j])&&dist[j]<mindist){
				v=j; 
				mindist=dist[j]; 
			} 
		}									
		s[v]=true; 
		for(int j=1;j<=n;j++)
			if((!s[j])&&edge[v][j]<INF)
				if(dist[j]>dist[v]+edge[v][j])
					dist[j]=dist[v]+edge[v][j];   
	}
	return dist[n]; 
} 

int main()
{
	int A,B,C;
	scanf("%d %d",&n,&m); 
	while(m||n){
		memset(edge,0,sizeof(edge)); 
		for(int i=0;i<m;i++){ 
			scanf("%d %d %d",&A,&B,&C); 
			edge[A][B]=edge[B][A]=C; 
		} 
		for(int i=0;i<110;i++)
			for(int j=0;j<110;j++)
				if(!edge[i][j])
					edge[i][j]=INF; 
		printf("%d\n",dij(1));
		scanf("%d %d",&n,&m); 
	} 
	return 0; 
} 

猜你喜欢

转载自blog.csdn.net/xizi_ghq/article/details/81171720