原题链接 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. spark异常篇-OutOfMemory:GC overhead limit exceeded

    执行如下代码时报错 # encoding:utf-8 from pyspark import SparkConf, SparkContext from pyspark.sql import Spark ...

  2. react项目中关于img标签的src属性的使用

    在一个html文件中,img的src属性赋值为相对路径或绝对路径的字符串即可访问到图片.如下: <img src="../images/photo.png"/> 但在j ...

  3. Codeforces 1189F. Array Beauty

    传送门 首先可以注意到序列里面元素的顺序对答案是没有影响的,所以二话不说先排序再看看怎么搞 考虑枚举每种子序列可能产生的贡献并算一下产生这个贡献的子序列有多少 考虑设 $F(x)$ 表示选择的元素差值 ...

  4. hdu 5446 lucas+crt+按位乘

    http://acm.hdu.edu.cn/showproblem.php?pid=5446 题意:题目意思很简单,要你求C(n,m)mod p的值 p=p1*p2*...pn; 题解:对于C(n,m ...

  5. SQLServer · 最佳实践 · 如何将SQL Server 2012降级到2008 R2-博客-云栖社区-阿里云

    迁移须知 使用SQLSERVER 2012的特性在SQL 2008 R2不支持,比如新的分页方式 此迁移操作手册适用于MSSQL2012到MSSQL2008R2的迁移 迁移使用微软提供的脚本生成和导入 ...

  6. php.ini中allow_url_fopen和allow_url_include的设置

    all_url_include在php 5.2以后添加,安全方便的设置(php的默认设置)为:allow_url_fopen=on;all_url_include=off;allow_url_fope ...

  7. java Map 四种遍历方法

    public static void main(String[] args) { Map<String, String> map = new HashMap<String, Stri ...

  8. IOS 改变UISearchBar的背景色

    之前网上提供的方法试了很多种  都不能很好的去掉背景色  ,修改背景色方法如下: searchbar.barStyle = UIBarStyleBlackTranslucent; searchbar. ...

  9. 判断两个list是否元素一样

    首先创建枚举 public enum TheType { type1 = , type2 = , type3 = } 1.如果不考虑顺序,即顺序不一样,只要元素都一样即可 List<TheTyp ...

  10. js对象中属性调用.和[] 两种方式的区别

    JS 调用属性一般有两种方法——点和中括号的方法. 标准格式是对象.属性(不带双引号),注意一点的是:js对象的属性,key标准是不用加引号的,加也可以,特别的情况必须加,如果key数字啊,表达式啊等 ...