最短路(diikstra和spfa)注释详细

本文详细介绍了使用Dijkstra算法的链式前向星和堆优化方法,以及SPFA(Shortest Path Faster Algorithm)算法来求解图中节点间的最短路径问题。两种算法通过不断更新节点的最短距离来逐步找到从源点到所有节点的最短路径。代码示例展示了如何在C++中实现这些算法。
摘要由CSDN通过智能技术生成

diikstra 链式前向星和堆优化(priority_queue)

注释部分是无优化的diikstra

#include<bits/stdc++.h>

using namespace std;
long long d[500001];
long long n,m,s;
long long vis[500001];
//代表每个顶点是否被访问
struct Edge
	{
	int next,to,val;
	} edge[500001];
int cnt=0;
long long head[500001];
void addegde(int b,int e,int v)//b=起点,e=终点,v=权值
	{
	cnt++;
	edge[cnt].to=e;
	edge[cnt].val=v;
	edge[cnt].next=head[b];
	head[b]=cnt;
	} //存图
struct node
	{
	int id,dis;//表示到第几节点和最短距离
	node(int b,int c)
		{
		id=b;
		dis=c;
		}
		bool operator<(const node &a)const
		{
			return dis>a.dis;
		}//保值小根堆的顺序 
	};
void df()
	{
	memset(d,0x3f3f3f3f,sizeof(d));
	memset(vis,0,sizeof(vis));
	d[s]=0;
//	for(int i=1; i<=n; i++)//遍历每个点
//		{
//		int k=0;
	d[0]=0x3f3f3f3f;
	priority_queue<node>q;//创建小根堆
	q.push(node(s,d[s]));//将节点和最短距离入队
	while(!q.empty())
		{
		node k=q.top();//取出对头,离s点最近
		q.pop();//弹出
		if(vis[k.id])continue;//如果已经走过跳过下面步骤
		vis[k.id]=1;
		for(int i=head[k.id]; i!=0; i=edge[i].next) //优化d数组,代表遍历从同一起点出发能到达的所有点
			{
			if(d[edge[i].to]>d[k.id]+edge[i].val)//判断从同一起点出发到同一终点的距离,是直接走快,还是从中介点k走快
				{
				d[edge[i].to]=d[k.id]+edge[i].val;
				q.push(node(edge[i].to,d[edge[i].to]));
				}
			}
		}
	}
/*for(int i=1; i<=n; i++) //找到距离出发点最近的路
	{
	if(vis[i]==0&&d[k]>d[i])
		{
		k=i;//k存的是所进过的点中距离最短的
		}
	}
if(k==0)//没有找到就退出循环
	{
	break;
	}
vis[k]=1;//标记为以找到
for(int i=head[k]; i!=0; i=edge[i].next) //优化d数组,代表遍历从同一起点出发能到达的所有点
	{
	if(d[edge[i].to]>d[k]+edge[i].val)//判断从同一起点出发到同一终点的距离,是直接走快,还是从中介点k走快
		{
		d[edge[i].to]=d[k]+edge[i].val;
		}

	}*/

//		}

int main()
	{


	scanf("%d%d%d",&n,&m,&s);
	for(int i=1; i<=m; i++)
		{
		int x,y,l;
		scanf("%d%d%d",&x,&y,&l);
		addegde(x,y,l);
		}
	df();
	for(int i=1; i<=n; i++)
		{
		printf("%d ",d[i]);
		}

	}

spfa

#include<bits/stdc++.h>

using namespace std;
int d[100001];
int vis[100001];
int s,n,m;
struct Edge
	{
	int next,to,val;
	} edge[500001];
int cnt=0;
long long head[500001];
void addegde(int b,int e,int v)//b=起点,e=终点,v=权值
	{
	cnt++;
	edge[cnt].to=e;
	edge[cnt].val=v;
	edge[cnt].next=head[b];
	head[b]=cnt;
	} //存图
void spfa()
	{
	memset(d,0x3f3f3f3f,sizeof(d));
	vis[s]=1;
	d[s]=0;
	queue<int>q;
	q.push(s);
	while(!q.empty())
		{
		int k=q.front();
		q.pop();
		vis[k]=0;
		for(int i=head[k]; i!=0; i=edge[i].next)
			{

			if(d[edge[i].to]>d[k]+edge[i].val)
				{
				d[edge[i].to]=d[k]+edge[i].val;
				if(vis[edge[i].to]==0)//判断是否放入过对列,如果没有加入队伍
					{
					vis[edge[i].to]=1;
					q.push(edge[i].to);
					}

				}
			}
		}
	}
int main()
	{

	scanf("%d%d%d",&n,&m,&s);
	for(int i=1; i<=m; i++)
		{
		int x,y,l;
		scanf("%d%d%d",&x,&y,&l);
		addegde(x,y,l);
		}
	for(int i=1; i<=n; i++)
		{
		addegde(0,i,0);
		}
	spfa();
	for(int i=1; i<=n; i++)
		{
		cout<<d[i]<<" ";
		}
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值