Dijkstra算法详解优化

介绍

Dijkstra算法是用来解决最短路径问题的一个常用算法;常用于解决单源最短路径问题,即给定一个起点S,求出其到图各个顶点的最小距离。其本质思想是贪心思想

解释

图文解释

https://blog.csdn.net/lbperfect123/article/details/84281300

文字解释

先建立数组:

vector<node>G[100005];//实现图(邻接表实现)
int dis[100005];//记录起点s到j的最短距离
bool visted[100005];//判断顶点j是否访问过
【注意】要初始化d[],G[][]

1.每次从未攻占的城市中选择据s最近的城市【u】,进行攻占;
2.以u为中介,优化所有能从u到达的&未访问的节点
3.执行n次上面两步操作;

代码实现

下面是一个模板。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
/*
思路:
	
*/
struct node{
	int to;//顶点 
	int val;//边的长度 
	node(int a,int b){
		to=a;
		val=b;
	}
};
vector<node>G[100005];
int dis[100005];
bool visted[100005];
int n;
void Dijkstra(int s){
	fill(dis,dis+100005,inf);//初始化 
	dis[s]=0;//s到s最近~ 
	for(int i=1;i<=n;i++){//找出未访问的定点中据起点最近的点 
		int u=-1,Min=INT_MAX; 
		for(int j=1;j<=n;j++){
			if(!visted[j]&&Min>dis[j]){
				u=j;
				Min=dis[j];
			}
		}//找出距离s的最近的 & 未访问的 点u 
		if(u==-1)return;
		visted[u]=1;//标记为已经访问 
		for(int j=0;j<G[u].size();j++){
			int f=G[u][j].to;
			int val=G[u][j].val;
			if(!visted[f]&&dis[f]>dis[u]+val)
				dis[f]=dis[u]+val;
			//更新dis[] 
		}
	}
}
int main(){
	int m,s;
	cin>>n>>m>>s;
	while(m--){
		int u,v,w;
		cin>>u>>v>>w;
		G[u].push_back(node(v,w));
		G[v].push_back(node(u,w));
	}
	Dijkstra(s);
	cout<<dis[1];
	for(int i=2;i<=n;i++)
		cout<<" "<<dis[i];
   return 0;
}

拓展

只会模板是不能够应对复杂(gou)多变的题目的;下面就来讨论一些最短路径之外的附加条件(即第二标尺)如何实现;

1.再增加一个边权

如果要考虑经过一条边时有花费,求在保证路径最短的情况下,花费最少。
思路

再加一个量
struct node{
	int to;//顶点 
	int val;//边的长度 
	int cost;//过边的花费
	node(int a,int b){
		to=a;
		val=b;
	}
};

代码实现

for(int j=0;j<G[u].size();j++){
			int f=G[u][j].to;
			int val=G[u][j].val;
			if(!visted[f]){
				if(dis[f]>dis[u]+val)//dis[]能更新 
					dis[f]=dis[u]+val;
				else if(dis[f]==dis[u]+val&&cost[f]>cost[u]+G[u][j].cost)
					 cost[f]>cost[u]+G[u][j].cost;
				//当路径最优时,保证花费最少
			} 
		}

2.再增加一个点权

情况与增加边权类似,不再赘述。

3.求最短路径条数

int num[100005];//记录起点s到j的最短路径条数。
for(int j=0;j<G[u].size();j++){
			int f=G[u][j].to;
			int val=G[u][j].val;
			if(!visted[f]){
				if(dis[f]>dis[u]+val){
					dis[f]=dis[u]+val;
					num[f]=num[u];//最短路径更新时,num[u]覆盖num[f] 
				} 
				else if(dis[f]==dis[u]+val){
					num[f]+=num[u];
					//最短距离相同时累加 
				}	
			} 
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高冷小伙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值