Dijkstra算法(链式向前星代码)

Luck_ZY will AK IOI(口号,勿在意)

发一篇小小的博客,关于新学的Dijkstra算法。

蒟蒻一直喜欢用暴力而简单的Floyd算法,但是作为一个基础算法,Dijkstra算法还是必须要会的

算法用途

Dijkstra算法是用来处理最短路径问题

主要寻找从某一起点到其余所有的点的最短路径

算法实现

Dijkstra算法主要用贪心算法,先存下起点到每一个点的距离,对于与起点不联通的点,到起点的距离记为正无穷,之后进行松弛操作,及在有中间点进行中转后,到起点的距离要更近,更新到该点的最小距离

 

对于这样一个有向图,如果以0为起点,所求的为其他所有点到0点的最短距离

若设置一个数组来储存每一个点到0的距离

设INF为一个无穷大的数

设 dis[].

数组dis[i]表示点i到起点的距离

dis[i]={0,1,12,INF,INF,INF}

之后对于点3,由于通过点1中转的路径小于INF,所以dis[3]=4

以此类推,dis[2]=8,dis[3]=4,dis[4]=13,dis[5]=17

代码实现:

1.存图

很简单,一般存图都会选用二维数组or邻接表or邻接矩阵

最直接的方法二维数组:

a[u][v];//表示从u指向v的一条边

我就直接上代码了

我这个人没别的优点,就是写代码时喜欢写注释,一些dalao可能会觉得啰嗦,但我还是写了

#include<bits/stdc++.h>
#define M 10005//M 表示最大的点数
using namespace std;
const int N=1e9+7;//初始时赋值的最大值 
int n,m,s;//n储存点数,m储存边,s储存start
int a[M][M];//用来储存有向边 
bool vis[M]={false};//被用来储存点是否被查看过 
int dis[M];//储存起点到每个点的最短路 
/*
	将a数组的每一个点的权值都设置成正无穷
	在储存边u->v的权值w时,储存a[u][v]的值为w
	
	将dis数组初始值also设置成正无穷 
*/
void Dijkstra(int s){//s为起点
//Dijkstra函数的作用就是求所有的点到起点的最小值
	fill(dis,dis+M,N);//将dis数组的值赋为最大值
	dis[s]=0;//以s到s的最小距离为0
	for(int i=1;i<=n;i++)
	/*
	进行n次循环。
	由于总共有n个点,故n次循环,就可以对每一个点进行访问
	每一次访问,都要对所有值进行更新 
	*/ 
	{ 
		int u=-1;//u用来表示到s最小值的点
		int MIN=N;
		for(int j=1;j<=n;j++)
		{
			if(vis[j]==false&&dis[j]<MIN)
			//条件(点j没有被访问过&&s->j有边&&s到点j的距离小于MIN) 
			{
				u=j;//到s最小的为点j,将j更新到u
				MIN=dis[j];//更新最小值min 
			}
		}
		if(u==-1) return;//如果u的值为-1,说明没有与s联通的边
		vis[u]=true;//u has been 访问过
		for(int k=1;k<=n;k++){
			//寻找与u相连的边 
			if(vis[k]==false&&a[u][k]!=N)
			//k点没有被访问过&&存在u到点k的边 
			{
				if(dis[u]+a[u][k]<dis[k])
				//以点u为中介的情况更优 
				{
					dis[k]=dis[u]+a[u][k];
				}
			}
		} 
	} 
} 
int main (){
	ios::sync_with_stdio(false);
	cin>>n>>m>>s;
	fill(a[0],a[0]+M*M,N);
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		a[u][v]=w;
	}
	Dijkstra(s);//begin 
	for(int i=1;i<=n;i++){
		cout<<dis[i]<<' '; 
	}
	return 0;
} 

。。。

问题

这个代码你会发现编译.运行&样例都能过

But MLE or RE

要不就是数组太大要不就开太小

太多的空间被浪费

于是就需要学习一个新东西,叫做链式向前星

我解释不清

直接上代码吧

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<memory.h>
#define MAXN 1000010
 
using namespace std;
 
const int INF=1e9+77;
int n;//point
int m;//edge
int start;//source point
int dis[MAXN];//best way
bool visit[MAXN];//whether visited
typedef struct Edge{
	int next;//next edge with the same head[]
	int to;//next point
	int w;//len
}Edge;
Edge edge[MAXN];
int head[MAXN];
int tot;
 
void init()
{
	memset(dis,INF,sizeof(dis));
	memset(visit,false,sizeof(visit));
	memset(head,-1,sizeof(head));
	tot=0;
}
 
void add(int u,int v,int wi)
{
	edge[tot].to =v;
	edge[tot].w =wi;
	edge[tot].next =head[u];
	head[u]=tot++;
}
 
void dijkstra(int s){
	int min,pos;
	while(1){
		min=INF;
		pos=-1;
		for(int i=1;i<=n;i++)
		{
			if(!visit[i]&&min>dis[i])
			{
				min=dis[i];
				pos=i;
			}
		}
		if(pos==-1)
		{
			break;
		}
		visit[pos]=true;
		for(int i=head[pos];i!=-1;i=edge[i].next )
		{
			int t=edge[i].to ;
			if(!visit[t]&&dis[t]>(dis[pos]+edge[i].w ))
			{
				dis[t]=dis[pos]+edge[i].w ;
			}
		}
	}
	return;
}
 
int main()
{
	init();
	scanf("%d%d%d",&n,&m,&start);
	dis[start]=0;
	for(int i=1;i<=m;i++)
	{
		int u,v,wi;
		scanf("%d%d%d",&u,&v,&wi);
		add(u,v,wi);
	//	add(v,u,wi);
	}
	dijkstra(start);
	for(int i=1;i<=n;i++)
	{
		cout<<dis[i]<<' ';
	}
	return 0;
 } 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值