zsyz_ZZY的博客

zsyz_ZZY的博客

luogu P3371 【模板】单源最短路径

题目传送门:https://www.luogu.org/problemnew/show/P3371



题意:

有n个点,m条边,一个起点st,求st到每个点的最短路径的长度。



思路1:

spfa。


代码:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
queue<int> f;
	struct node{int x,y,z,next;} a[500010];
	int last[10010],dis[10010];
	bool bz[10010];
	int n,m,st,len=0;
void ins(int x,int y,int z)
{
	a[++len].x=x;a[len].y=y;a[len].z=z;a[len].next=last[x];last[x]=len;
}
int spfa()
{   
	memset(bz,true,sizeof(bz));
	bz[st]=false;
	memset(dis,63,sizeof(dis));
	dis[st]=0;
	f.push(st);
	while(!f.empty())
	{
		int x=f.front();
		f.pop();
		bz[x]=true;
		for(int i=last[x];i;i=a[i].next)
		{
			int y=a[i].y;
			if(dis[x]+a[i].z<dis[y])
			{
				dis[y]=dis[x]+a[i].z;
				if(bz[y])
				{
					bz[y]=false;
					f.push(y);
				}
			}
		}
	}
}
int main()
{
	int x,y,z;
	scanf("%d %d %d",&n,&m,&st);
	for(int i=1;i<=m;i++)
	{
		scanf("%d %d %d",&x,&y,&z);
		ins(x,y,z);
	}
	spfa();
	for(int i=1;i<=n;i++)
		printf("%d ",dis[i]<1061109567?dis[i]:2147483647);
}



思路2:

spfa+SLF优化。

所谓SLF优化指如果当前经过松弛的dis[y]小于队列首,就加入队首,否则加入队尾。

用STL中的deque(双端队列)比较好用,建议随时打上(卡卡常,大佬请无视)

PS:LLL优化蒟蒻表示不会(据说效果不明显,大佬请无视)。


代码:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
deque<int> f;
	struct node{int x,y,z,next;} a[500010];
	int last[10010],dis[10010];
	bool bz[10010];
	int n,m,st,len=0;
void ins(int x,int y,int z)
{
	a[++len].x=x;a[len].y=y;a[len].z=z;a[len].next=last[x];last[x]=len;
}
int spfa()
{   
	memset(bz,true,sizeof(bz));
	bz[st]=false;
	memset(dis,63,sizeof(dis));
	dis[st]=0;
	f.push_back(st);
	while(!f.empty())
	{
		int x=f.front();
		f.pop_front();
		bz[x]=true;
		for(int i=last[x];i;i=a[i].next)
		{
			int y=a[i].y;
			if(dis[x]+a[i].z<dis[y])
			{
				dis[y]=dis[x]+a[i].z;
				if(bz[y])
				{
					bz[y]=false;
					if(!f.empty()&&dis[y]<dis[f.front()]) f.push_front(y); else f.push_back(y);
				}
			}
		}
	}
}
int main()
{
	int x,y,z;
	scanf("%d %d %d",&n,&m,&st);
	for(int i=1;i<=m;i++)
	{
		scanf("%d %d %d",&x,&y,&z);
		ins(x,y,z);
	}
	spfa();
	for(int i=1;i<=n;i++)
		printf("%d ",dis[i]<1061109567?dis[i]:2147483647);
}


思路3:

dijkstra+堆优化。

代码:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct node1
{
    int id,d;
    friend bool operator <(node1 x,node1 y)
    {
        return x.d>y.d;
    }
};
priority_queue<node1> f;
    struct node2{int x,y,z,next;} a[500010];
    int last[10010],dis[10010];
    bool bz[10010];
    int n,m,st,len=0;
void ins(int x,int y,int z)
{
    a[++len].x=x;a[len].y=y;a[len].z=z;a[len].next=last[x];last[x]=len;
}
void dijkstra()
{
    memset(bz,true,sizeof(bz));
    memset(dis,63,sizeof(dis));
    dis[st]=0;
    f.push((node1){st,0});
    while(!f.empty())
    {
		int x=f.top().id,p=f.top().d;
		f.pop();
		if(!bz[x]) continue;
        bz[x]=false;
        dis[x]=p;
        for(int i=last[x];i;i=a[i].next)
        {
            int y=a[i].y;
            if(dis[x]+a[i].z<dis[y])
            {
                dis[y]=dis[x]+a[i].z;
				f.push((node1){y,dis[y]});
            }
        }
    }
}
int main()
{
    int x,y,z;
    scanf("%d %d %d",&n,&m,&st);
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&x,&y,&z);
        ins(x,y,z);
    }
    dijkstra();
    for(int i=1;i<=n;i++)
        printf("%d ",dis[i]<1061109567?dis[i]:2147483647);
}

建议用思路2(如果不会,也可以用思路1)和思路3,比较快。

阅读更多
个人分类: spfa 最短路
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

luogu P3371 【模板】单源最短路径

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭