dijkstra算法,单源最短路径算法,含记录路径

23 篇文章 0 订阅
11 篇文章 0 订阅

v0为源点,N为邻接矩阵的阶,edge为邻接矩阵,maxn为常量,path用来保存路径节点的前驱,D用来保存最短路径权重和。顺便说一下,严蔚敏的数据结构中的这个算法只能保存最短路径上的节点,并得不到先后顺序。

//从某个点到其余各点间的最小距离
void dijkstra(int v0, int N, int edge[][maxn], int path[], int D[]) {
	for (int v = 0; v < N; v++) {
		path[v] = -1;
		final[v] = false;
		D[v] = edge[v0][v];
	}
	path[v0] = v0;
	D[v0] = 0;
	final[v0] = true; // final[i]为 true 时,表示i在集合S(已求得最短路径的终点的集合)中
					  //开始主循环,每次求得v0到某个v顶点的最短路径,并加v到S中
	for (int i = 1; i < N; i++) {
		int v = -1; //中途点
		int min = INF; //当前所知的离v0点的最近距离
		for (int w = 0; w < N; w++)
			if (!final[w] && D[w] < min) { //点 w 在(V - S)中
				min = D[w]; // 点 w 离 v0 更近
				v = w;
			}
		if (v == -1)
			break;
		final[v] = true;
		for (int w = 0; w < N; w++) //更新当前最短路径及距离
			if (!final[w] && D[w] > min + edge[v][w]) {
				path[w] = v;//path[w]记录d[w]暂时最短路径的最后一个
				//中途节点mv,表明d[w]最后一段从点v到点w
				D[w] = min + edge[v][w];
			}// if
	}// for
}//挑战程序设计竞赛中的这个算法好像更短


下面用一个数组track倒序存储v0到end点的最短路径所经过的点,但是若路径不唯一,这个算法只能得到一个解,在路径最短的前提下,并不嫩保证得到经过节点最少的路径

int getTrack(int v0, int end, int track[], int path[]) {
	track[0] = end;
	int cur = 1;
	int pre = end;
	while (pre != -1 && pre != v0) {  //若P[v][w]为true,则w是从v0到v当前求得最短路径的顶点
		pre = path[pre];
		track[cur++] = pre;
	}
	track[cur - 1] = v0;
	return cur; // 从0开始,track[]倒序保存路径,返回走过点数の个数cur
}

zzuwenjie 2017-3-19 22:54:49

代码中这样一句,d[w] = min(d[w], minV + d[v][w]);小心溢出,所以不直接相连的边距离不能设置为INT_MAX

void Dijkstra(int v0, int n, int pic[][maxn], int d[]) {
	for (int i = 1; i <= n; ++i) {
		d[i] = pic[v0][i];
		final[i] = false;
	}
	final[v0] = true;		
	d[v0] = 0;
	for (int i = 1; i < n; ++i) {
		int minV = INT_MAX, u = -1;  
		for (int w = 1; w <= n; ++w)
			if (!final[w] && minV > d[w]) {
				minV = d[w];
				u = w;
			}
		if (u == -1)
			break;
		final[u] = true;
		for (int w = 1; w <= n; ++w)
				d[w] = min(d[w], minV + pic[u][w]); 
	}
} 

郑大OJ10400海岛争霸

求最短路上的最大值

#include <cstdio> 
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int n, m;
const int maxn = 112;
int pic[maxn][maxn];
int d[maxn];
bool final[maxn];
void dijkstra(int v0, int n, int pic[][maxn], int d[]) {
	for (int i= 1;i <= n; ++i) {
		d[i] = pic[v0][i];
		final[i] = false;
	}
	final[v0] = true;
	for (int i = 1; i < n; ++i) {
		int minV = INF, u = v0;
		for (int w= 1; w <= n; ++w) {
			if(!final[w] && minV > d[w]) {
				minV = d[w];
				u = w;
			}
		}
		if (u == -1)
			break;
		final[u] = true;
		for(int w = 1; w <= n; ++w)
			if (!final[w])
				d[w] = min(d[w], max(d[u], pic[u][w]));
	}
}
int main()
{
	while(~scanf("%d%d", &n, &m)) {
		for (int i = 1; i <= n; ++i)
			for (int j = 1; j <= i; ++j) 
				pic[i][j] = pic[j][i] = (i == j ? 0 : INF);
		for (int i= 0;i < m; ++i) {
			int x, y, d;
			scanf("%d%d%d", &x, &y, &d);
			pic[x][y] = pic[y][x] = min(pic[x][y], d);
		}
		scanf("%d", &m);
		while(m-- > 0) {
			int x, y;
			scanf("%d%d", &x, &y);
			dijkstra(x, n, pic, d);
			printf("%d\n", d[y] == INF ? -1 : d[y]);
		} 
	}
	
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值