P3371 模板单源最短路径(弱化版)

Posted michael666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3371 模板单源最短路径(弱化版)相关的知识,希望对你有一定的参考价值。

P3371 【模板】单源最短路径(弱化版)

题目背景

本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 P4779

题目描述

如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。

输入格式

第一行包含三个整数 n,m,sn,m,s,分别表示点的个数、有向边的个数、出发点的编号。

接下来 mm 行每行包含三个整数 u,v,wu,v,w,表示一条 u o vuv 的,长度为 ww 的边。

输出格式

输出一行 nn 个整数,第 ii 个表示 ss 到第 ii 个点的最短路径,若不能到达则输出 2^{31}-12311。

输入输出样例

输入 #1
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
输出 #1
0 2 4 3

说明/提示

【数据范围】
对于 20\%20% 的数据:1le n le 51n5,1le m le 151m15;
对于 40\%40% 的数据:1le n le 1001n100,1le m le 10^41m104;
对于 70\%70% 的数据:1le n le 10001n1000,1le m le 10^51m105;
对于 100\%100% 的数据:1 le n le 10^41n104,1le m le 5 imes 10^51m5×105,保证数据随机。

对于真正 100\%100% 的数据,请移步 P4779。请注意,该题与本题数据范围略有不同。

样例说明:

技术图片

图片1到3和1到4的文字位置调换

思路

这里使用使用STL队列,首先用数组dis记录起点到每个结点的最短路径,用邻接表来存储图,用vis数组记录当前节点是否在队列中

具体操作

用队列来保存待优化的结点(类似于BFS),优化时每次取出队首结点,并且用队手节点来对最短路径进行更新并进行松弛操作

如果要对所连点的最短路径需要更新,且改点不在当前的队列中,就将改点加入队列然后不断进行松弛操作,直至队列空为止。

AC代码如下

技术图片
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x=0,k=1; char c=getchar();
    while(c<0||c>9){if(c==-)k=-1;c=getchar();}
    while(c>=0&&c<=9)x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*k;
}
#define maxn 10005
#define maxm 500005
#define inf 2147483647
int n,m,s,tot,di[maxn],t[maxn];
bool vi[maxn];
struct e
{
      int next,to,w;
}h[maxm];
void add(int u,int v,int w)
{
    h[++tot].next=t[u];
    h[tot].to=v;
    h[tot].w=w;
    t[u]=tot;
}
queue<int> q;
inline void sp()
{
    for(int i=1; i<=n; i++)
    {
        di[i]=inf;
    }
    int u,v;
    q.push(s);
    di[s]=0; 
    vi[s]=1;
    while(!q.empty())
    {
        u=q.front();
        q.pop();
        vi[u]=0;
        for(int i=t[u];i;i=h[i].next)
        {
            v=h[i].to;
            if(di[v]>di[u]+h[i].w)
            {
                di[v]=di[u]+h[i].w;
                if(!vi[v])
                {
                      vi[v]=1;
                      q.push(v);
                }
            }
        }
    }
}
int main(){
    n=read(),m=read(),s=read();
    for(int i=1,u,v,w;i<=m;i++)
    {
        u=read(),v=read(),w=read();
        add(u,v,w);
    }
    sp();
    for(int i=1; i<=n; i++)
    {
        printf("%d ",di[i]);
    }
    return 0;
}
View Code

注意

这里需要注意一点,就是在原题中的一个条件“如果没有结果,则输出2^31-1”.

本人就是在这里丢掉了一个测试点的分QWQ。

以上是关于P3371 模板单源最短路径(弱化版)的主要内容,如果未能解决你的问题,请参考以下文章

luogu P3371 & P4779 ---单源最短路径spfa & 最大堆优化Dijkstra

P4779 模板单源最短路径(标准版) 题解

单源最短路径模板(弱化版)

洛谷 P3371 单源最短路径(Java版)

P3371 模板单源最短路径 如题

洛谷 P3371 模板单源最短路径