Dijkstra算法

Dijkstra算法

Dijkstra算法解决的是单源最短路径问题,即给定图 G ( V , E ) G(V,E) G(V,E)和起点 s s s,求从给定起点 s s s到其他顶点的最短距离。

算法思想

设置集合 V V V为未访问的顶点集, S S S为已被访问的顶点的集合,然后执行n次(顶点个数)下面两步:
①每次从集合 V V V中选择与起点 s s s的最短距离最小的一个顶点,记为 u u u,设置为已访问并加入 S S S
②令顶点 u u u为中介点,遍历 s s s通过 u u u能够到达的顶点,如果通过 u u u能够缩短 s s s到其他顶点的距离,则优化最短距离。

程序模板

邻接矩阵版

const int MAXV=1000;
const int INF=0x3f3f3f3f;
bool vis[MAXV]= {false};
int n,G[MAXV][MAXV];
//记录最短路径中每个点的前一个顶点
vector<int> pre[MAXV];
//起点到达各点的距离
int d[MAXV];

void dijkstra(int s) {
	fill(d,d+MAXV,INF);
	//起点到自身的距离为0
	d[s]=0;
	for(int i=0; i<n; i++) {
		int u=-1,MIN=INF;
		for(int j=0; j<n; j++) {
			if(!vis[j] && d[j]<MIN) {
				u=j;
				MIN=d[j];
			}
		}
		//找不到小于INF的d[u],说明剩下的点不连通或者全部访问过了
		if(u==-1) return;
		vis[u]=true;
		for(int v=0; v<n; v++) {
			if(!vis[v] && G[u][v]!=INF){
				if(d[u]+G[u][v]<d[v]) {
					d[v]=d[u]+G[u][v];
					//由于最短路径更新,所以v的前一顶点也要更新
					pre[v].clear();
					pre[v].push_back(u);
				}else if(d[u]+G[u][v]==d[v]){
					pre[v].push_back(u);
				}
			}
		}
	}
}

邻接表版

const int MAXV=1000;
const int INF=0x3f3f3f3f;
bool vis[MAXV]= {false};
vector<int> pre[MAXV];
int n,d[MAXV];
struct Node {
//v为下一顶点,dis为距离
	int v,dis;
};
vector<Node> adj[MAXV];

void dijkstra(int s) {
	fill(d,d+MAXV,INF);
	d[s]=0;
	for(int i=0; i<n; i++) {
		int u=-1,MIN=INF;
		for(int j=0; j<n; j++) {
			if(!vis[j] && d[j]<MIN) {
				u=j;
				MIN=d[j];
			}
		}
		if(u==-1) return;
		vis[u]=true;
		//只有下面不同
		for(int j=0; j<adj[u].size(); j++) {
			int v=adj[u][j].v;
			if(!vis[v]){
				if(d[u]+adj[u][j].dis<d[v]) {
					d[v]=d[u]+adj[u][j].dis;
					pre[v].clear();
					pre[v].push_back(u);
				}else if(d[u]+adj[u][j].dis==d[v]){
					pre[v].push_back(u);
				}
			}
		}
	}
}

第二标尺

有些题目需要结合一些别的条件,称为第二标尺,比如点权、边权(花费)、路径数量等,可以使用上述的模板得出pre之后,结合DFS来求出考虑第二标尺的结果:
我们需要新增加三个变量
①全局变量的第二标志最优值optValue
②记录最优路径的path(vector)
③记录DFS遍历时的临时路径tmpPath(vector)

int optValue;
vector<int> path,tmpPath;

void DFS(int v,int s){
//	递归边界 
	if(v==s){
		tmpPath.push_back(v);
		int value;
//		************** 
//		根据题意,计算此路径的 value(第二标尺) 
//		************** 
		if(value>optValue){
			optValue=value;
			path=tmpPath;
		}
		tmpPath.pop_back();
		return;
	}
//	递归式 
	tmpPath.push_back();
	for(int i=0;i<pre[v].size();i++){
		DFS(pre[v][i]);
	}
	tmpPath.pop_back();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值