【堆优化dij】洛谷P4779 【模板】单源最短路径(标准版)

版权声明:转载无所谓的。。。 https://blog.csdn.net/xuxiayang/article/details/82807778

链接

https://www.luogu.org/problemnew/show/P4779


大意

给定一张 n n m m 条边的有向无负权图,求 s s 点到所有点的最短路径


思路

标准的 s p f a spfa 会被卡。。。

加点优化还是能过的。。。

这里主要讨论 d i j _ h e a p dij\_heap 做法。。。

就是因为 d i j dij 每次找与他相邻的边中最小的那条太慢了,这里其实是用了贪心的思想,有最大最小就有堆啊。。。

所以完全可以在 l o g   n log\ n 的时间内找到相邻的边中最小的,然后直接转移

代码看起来比较像 s p f a spfa 呀,可以不能处理负环
当然也可以用johnson


代码

#include<cstdio>
#include<queue>
using namespace std;int l[100001],tot,dis[100001],s,n,m;
inline int read()//输入优化
{
	int d=1,f=0;char c;
	while(c=getchar(),c<48||c>57)if(c=='-')d=-1;f=(f<<3)+(f<<1)+c-48;
	while(c=getchar(),c>47&&c<58) f=(f<<3)+(f<<1)+c-48;
	return d*f;
}
struct node{int next,to,w;}e[500001];//边
struct heap{int u,d;};//堆
inline bool operator <(heap x,heap y){return x.d>y.d;}//小的在前面
inline void add(register int u,register int v,register int w){e[++tot]=(node){l[u],v,w};l[u]=tot;}//建边
bool vis[100001];//判断会不会重新走过。。。
inline void Dijstra_heap()
{
	for(register int i=0;i<=n;i++) dis[i]=2147483647;
	dis[s]=0;
	priority_queue<heap>q;
	q.push((heap){s,0});vis[s]=true;
	while(q.size())
	{
		heap u=q.top();q.pop();//取出堆顶
		int x=u.u,d=u.d;vis[x]=true;//标记
		for(register int i=l[x];i;i=e[i].next)//用其进行拓展
		{
			int y=e[i].to,w=e[i].w;
			if(dis[x]+w<dis[y])
			{
				dis[y]=dis[x]+w;//转移
				if(!vis[y]) q.push((heap){y,dis[y]}),vis[y]=true;//没有标记过则标记并放入
			}
		}
		vis[x]=false;//记得取消标记(没有也可以)
	}
	return;
}
signed main()
{
	n=read();m=read();s=read();
	for(register int i=1,x,y,z;i<=m;i++) x=read(),y=read(),z=read(),add(x,y,z);//输入
	Dijstra_heap();//dij
	for(register int i=1;i<=n;i++) printf("%d ",dis[i]);//输出
}

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/82807778
今日推荐