原题链接 https://www.luogu.org/problemnew/show/P4779

若还未食用弱化版的同学请先做这个qwq https://www.luogu.org/problemnew/show/P3371

刚刚做完了弱化版的我,看到了这个标准版 双倍经验美滋滋qwq

把弱化版的SPFA模板打上去,改了下数据范围,提交!悲催的TLE了四个点!

很显然,这个题的数据是卡SPFA的,使得时间复杂度是SPFA最坏的复杂度!

那咋办呢?我们看到了题目中已经说明了没有负权边,那么我们就可以用时间复杂度更为稳定的Dijkstra算法!

介绍一下下算法原理及实现:

假设我们有白点和蓝点,蓝点表示还未被松弛的点,白点表示已经松弛过的点,vis[i]=1代表是白点已经被松弛过了,vis[i]=0代表是蓝点还未被松弛过。我们的目标就是将所有的蓝点转化成白点;

1.从起点s开始,松弛它所有的出边,若某条边松弛成功且这条边的终点不在队列里,就让它入队,将起点标记为白点:vis[s]=1;

2.找到一个距离起点s最小的点(用优先队列实现),若该点是蓝点,那么松弛它所有的出边,若某条边松弛成功且这条边的终点不在队列里,就让它入队,将起点标记为白点:vis[i]=1;

重复第2个步骤,直到队列为空。

Dijkstra为什么是正确的?

当所有边长都是非负数的时候,全局最小值不可能再被其他节点更新.所以在第22步中找出的蓝点xx必然满足:dis[x]:dis[x]已经是起点到xx的最短路径..我们不断选择全局最小值进行标记和拓展,最终可以得到起点到每个节点的最短路径的长度。

算法图解

1.选定A节点并初始化,如上述步骤3所示

2.执行上述 4、5两步骤,找出U集合中路径最短的节点D 加入S集合,并根据条件 if ( 'D 到 B,C,E 的距离' + 'AD 距离' < 'A 到 B,C,E 的距离' ) 来更新U集合

3.这时候 A->B, A->C 都为3,没关系。其实这时候他俩都是最短距离,如果从算法逻辑来讲的话,会先取到B点。而这个时候 if 条件变成了 if ( 'B 到 C,E 的距离' + 'AB 距离' < 'A 到 C,E 的距离' )如图所示这时候A->B距离 其实为 A->D->B

 

4.思路就是这样,往后就是大同小异了

链接:https://www.jianshu.com/p/ff6db00ad866

说了这么多,下面上代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int edge_sum; //暂时存边数
int n,m,s;
const int inf=1e9;
int read()
{
int a=;
char ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='')
{
a=a*+(ch-'');
ch=getchar();
}
return a;
}
int head[],vis[],dis[]; //head[i]表示以i结点为始点的最后一条出边,vis[i]表示i结点是否为白点,dis[i]表示i结点到起点s的最短距离
struct edge //定义一个结构体来存边的信息
{
int dis,pos,from,to,next;
bool operator < (const edge &x)const //重载小于号,根据dis来从小到大排序
{
return x.dis<dis;
}
}a[];
priority_queue<edge> q; //优先队列
void add(int from,int to,int dis) //链式前向星存图
{
edge_sum++;
a[edge_sum].next=head[from];
a[edge_sum].dis=dis;
a[edge_sum].from=from;
a[edge_sum].to=to;
head[from]=edge_sum;
}
int main()
{
n=read();m=read();s=read();
for(int i=;i<=m;i++)
{
int u=read();
int v=read();
int w=read();
add(u,v,w); //建图
}
for(int i=;i<=n;i++) dis[i]=inf,vis[i]=;//初始化
dis[s]=;
q.push((edge){,s}); //敲黑板,难点重点!!!我们优先队列定义的是edge类型的,所以我们放入一个edge类型的集合,集合中的第一个元素对应着结构体中的第一个成员,后之同理
//换句话说,这步操作就是将一个距离起点为0,编号为s的结点入队
while(!q.empty())
{
edge front=q.top(); //记录队列里的第一个元素,也就是dis最小的元素
q.pop(); //弹出队首元素
int wz=front.pos; //wz是该边的始点编号
if(vis[wz]==) continue; //如果该点已经在优先队列里了,那就没有松弛的必要了
vis[wz]=; //将始点标记为白点
for(int i=head[wz];i;i=a[i].next) //访问所有的出边
{
int zd=a[i].to; //这条边的终点
if(dis[zd]>dis[wz]+a[i].dis)
{
dis[zd]=dis[wz]+a[i].dis; //松弛
if(vis[zd]==) //若终点不在队列里的话
{
q.push((edge){dis[zd],zd}); //将松弛过的点都入队
}
}
}
}
for(int i=;i<=n;i++)
printf("%d ",dis[i]);
return ;
}

完结撒花qwq 双倍经验喽

P4779 【模板】单源最短路径(标准版)题解的更多相关文章

  1. [模板]单源最短路径(Dijkstra)

    如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 主要还是再打一遍最短路,这种算法我用的不多... #include<bits/stdc++.h> using namesp ...

  2. 洛谷P3371单源最短路径Dijkstra版(链式前向星处理)

    首先讲解一下链式前向星是什么.简单的来说就是用一个数组(用结构体来表示多个量)来存一张图,每一条边的出结点的编号都指向这条边同一出结点的另一个编号(怎么这么的绕) 如下面的程序就是存链式前向星.(不用 ...

  3. 【洛谷 p3371】模板-单源最短路径(图论)

    题目:给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 解法:spfa算法. 1 #include<cstdio> 2 #include<cstdlib> 3 #in ...

  4. 洛谷 P4779 【模板】单源最短路径(标准版) 题解

    P4779 [模板]单源最短路径(标准版) 题目背景 2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路. 然后呢? 100 ...

  5. P4779 【模板】单源最短路径(标准版)

    P4779 [模板]单源最短路径(标准版) 求单源最短路, 输出距离 Solution \(nlogn\) 堆优化 \(Djs\) Code #include<iostream> #inc ...

  6. 洛谷 P4779【模板】单源最短路径(标准版)

    洛谷 P4779[模板]单源最短路径(标准版) 题目背景 2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路. 然后呢? 10 ...

  7. 洛谷 P3371 【模板】单源最短路径(弱化版) 题解

    P3371 [模板]单源最短路径(弱化版) 题目背景 本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 P4779. 题目描述 如题,给出一个有向图,请输出从某一点出 ...

  8. 洛谷P4779 【模板】单源最短路径

    P4779 [模板]单源最短路径(标准版) 题目链接 https://www.luogu.org/problemnew/show/P4779 题目描述 给定一个 N个点,M条有向边的带非负权图,请你计 ...

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

    P3371 [模板]单源最短路径(弱化版) SPFA算法: SPFA 算法是 Bellman-Ford算法 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环.SPFA 最坏情况下复 ...

  10. P3371 【模板】单源最短路径(弱化版)(Dijkstra算法)

    题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包含三个整数N.M.S,分别表示点的个数.有向边的个数.出发点的编号. 接下来M行每行包含三 ...

随机推荐

  1. 【转】STM32的FSMC详解

    STM32的FSMC真是一个万能的总线控制器,不仅可以控制SRAM,NOR FLASH,NAND FLASH,PC Card,还能控制LCD,TFT. 一般越是复杂的东西,理解起来就很困难,但是使用上 ...

  2. Java 抽象类详解

    在<Java中的抽象方法和接口>中,介绍了抽象方法与接口,以及做了简单的比较. 这里我想详细探讨下抽象类. 一.抽象类的定义 被关键字“abstract”修饰的类,为抽象类.(而且,abx ...

  3. Servlet获取JSP中的汉字乱码问题解决方案

    1.String customerName=request.getParameter("customer_name");这样会出现乱码 解决方案很简单: String custom ...

  4. CPU vector operations

    CPU vector operations 原文:https://blog.csdn.net/wangeen/article/details/8602028 vector operations 是现代 ...

  5. C++性能榨汁机之伪共享

    C++性能榨汁机之伪共享 来源  http://irootlee.com/juicer_false_sharing/ 前言 在多核并发编程中,如果将互斥锁的争用比作“性能杀手”的话,那么伪共享则相当于 ...

  6. PHP 手机短信发送验证码

    点击链接加入群[php/web 学习课堂]:https://jq.qq.com/?_wv=1027&k=5645xiw 欢迎大家加入,一起讨论学习 本篇设计的知识点有点多,我会分类将,同学们可 ...

  7. SpringCloud之Ribbon负载均衡配置

    一.负载均衡解决方案分类及特征 业界主流的负载均衡解决方案有: 1.1 集中式负载均衡 即在客户端和服务端之间使用独立的负载均衡设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责 ...

  8. ASE19团队项目alpha阶段model组 scrum10 记录

    本次会议于11月14日,19时整在微软北京西二号楼sky garden召开,持续5分钟. 与会人员:Jiyan He, Kun Yan, Lei Chai, Linfeng Qi, Xueqing W ...

  9. php连接docker运行的mysql,显示(HY000/2002): Connection refused的解决办法

    php要连接docker中运行的mysql是不能用localhost, 127.0.0.1来连接的,因为每个docker运行容器的localhost 127.0.0.1都是自己容器本身,不是mysql ...

  10. html z-index

    如果你的悬浮的div被其他遮挡  那应该是遮挡的元素与它不是同级  可以考虑放在同一个父级目录下