模板——dijkstra单源最短路

传送门:https://www.luogu.com.cn/problem/P4779

dijstra 算法用于对单源最短路的求解问题,运用堆优化后,可以在O\((({n}+{m})\times\log_2{n})\)的复杂度内解决两点之间的最短路问题

实现方法:

  • dijstra 算法基于贪心的思想实现
  • 对于一个未更新的权值最小的节点x,将其标记为已走过,对于该节点x的所有出边y,边权为z,若存在 d[y]>d[x]+z,则令d[y]=d[x]+z,进行更新
  • 重复上述步骤,直至所有的节点均被标记

dijstra不适合用于存在负边权的图中

dijstra运用堆优化,可以有效地避免对其他无关的边进行的冗余运算,可以有效地提升其运算复杂度

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<math.h>
#include<queue>
#define ll long long
using namespace std;

const ll maxm=2e5+10;
int n,m,s,tot;
int edge[maxm],ver[maxm],next[maxm],head[maxm],v[maxm],dis[maxm];
priority_queue<pair<int,int> > q;

inline void add(const int u,const int v,const int w)\\邻接表存图,可以用vector代替
{
	ver[++tot]=v;
	edge[tot]=w;
	next[tot]=head[u];
	head[u]=tot;
}

inline void dij(int x)
{
	memset(dis,0x3f,sizeof(dis));\\初始化边权值
	memset(v,0,sizeof(v));
	dis[x]=0;
	q.push(make_pair(0,1));\\优先队列实现堆优化dijstra
	while(q.size()!=0)
	{
		int x=q.top().second;
		q.pop();
		if(v[x]==1) continue;
		v[x]=1;
		for(int i=head[x];i;i=next[i])
		{
			int y=ver[i];
			int z=edge[i];
			
			if(dis[y]>dis[x]+z)
			{
				dis[y]=dis[x]+z;
				q.push(make_pair(-dis[y],y));
			}
		}
	}
}

int main(void)
{
	scanf("%d%d%d",&n,&m,&s);
	
	for(int x,y,z;m;m--)
	{
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
	}
		
	dij(s);
	
	for(int i=1;i<=n;i++)
	{
		printf("%d ",dis[i]);
	}
	
	return 0;
}
posted @ 2020-07-11 09:30  雾隐  阅读(102)  评论(0编辑  收藏  举报