自TG滚粗后咕咕咕了这么久,最近重新开始学OI,也会慢慢开始更博了。。。。

最短路算法经典的就是SPFA(Bellman-Ford),Dijkstra,Floyd;

本期先讲两个经典的单源最短路算法:

首先是我最喜(hao)欢(xie)的SPFA(可惜经常被卡)

SPFA:

Warning:SPFA在OI竞赛中慎用,极易容易被卡!!!

基本流程:

从起点开始,每次将扫到的点入队,每个点遍历所有与其相连的点,并更新最短路,如果该点未入队,则将其入队;

均摊复杂度为$ O(KE) $(K=2),但因为SPFA在网格图中入队次数过多,导致卡成原始的Bellman-Ford($ o(VE) $),所以竞赛中不常用到(但还是要学会的);

丑陋的代码(洛谷P3371):

 #include<cstdio>
#include<algorithm>
using namespace std;
int n,m,x,y,z,tot,f[],q[],h,t,s,first[],nxt[],last[],en[],len[];
//f为记录最短路径的数组,q为队列;
//first,nxt,last,en,len为平平无奇的邻接表;
bool b[];
//判断是否在队列中
void add(int x,int y,int z)
{
++tot;
if(first[x]==) first[x]=tot; else nxt[last[x]]=tot;
en[tot]=y;
len[tot]=z;
last[x]=tot;
}
void SPFA(int x)
{
int k=first[x];
do
{
if((long long)len[k]+f[x]<f[en[k]])
{
f[en[k]]=len[k]+f[x];
if(not b[en[k]])
{
++t;
q[t]=en[k];
b[en[k]]=true;
}
}
k=nxt[k];
}
while(k!=);
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=;i<=m;++i)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
for(int i=;i<=n;++i)
f[i]=;
f[s]=;
h=;
t=;
SPFA(s);
while(h<=t)
{
SPFA(q[h]);
b[q[h]]=false;
++h;
}
for(int i=;i<=n;++i)
printf("%d ",f[i]);
return ;
}

Dijkstra:

最常用的最短路算法(蒟蒻的我最近才学会太菜了);

基本流程:

定义两个点的集合,S为已求出最短路的点集,T为未求出最短路的点集;

每次在T集合中找到一个Dis值最小的点,将其放入S集合中,并用它更新其他点的最短路;

由此,朴素的Dijkstra在每次选择操作中暴力枚举每个点复杂度为$ O(V) $,更新时的复杂度也为$ O(V) $,及时间复杂度为$ O(V^2) $;

聪(AK)明(IOI)的读者可能已经发现了,选择Dis值最小的点时,暴力枚举过于浪费,为了避免超时,我们可以用堆(或者线段树)优化为$ o(Vlog(E)) $;

每次选择时,直接访问堆的根节点,将其弹出,并把更新的节点压入堆中;(每次压入堆中不必要判是否已入堆,只需要开个bool数组记录该点是否已有最短路即可)

(甚至可以用斐波那契堆优化为$ o(E+Vlog(V)) $)

附上丑陋的代码(CodeChef CLIQUED):

 #include<cstdio>
#include<queue>
#include<iostream>
using namespace std;
const int MAXN=;
const long long INF=1e15+;
struct node
{
int pos;
long long dis;
bool operator <(const node &x)const
{
return x.dis<dis;
}
};
priority_queue<node> q;
int tot,first[MAXN],nxt[MAXN],last[MAXN],to[MAXN],len[MAXN];
//平平无奇的邻接表
int T,n,k,x,m,s;
long long dis[MAXN];
//dis为到每个点的最短路径
bool vis[MAXN];
//vis记录每个点是否已有最短路的值
void dijistra()
{
dis[s]=;
q.push((node){s,});
while(!q.empty())
{
node t=q.top();
int po=t.pos;
long long di=t.dis;
q.pop();
//取堆的根节点
if(vis[po])
continue;
//如果已有最短路,说明该点已更新过,无需更新
vis[po]=;
for(int i=first[po];i;i=nxt[i])
if(di+len[i]<dis[to[i]])
{
dis[to[i]]=di+len[i];
q.push((node){to[i],di+len[i]});
}
//常规松弛(更新最短路径)
}
}
void add(int x,int y,int z)
{
tot++;
if(first[x]==)
first[x]=tot;
else
nxt[last[x]]=tot;
last[x]=tot;
to[tot]=y;
len[tot]=z;
}
int main()
{
scanf("%d",&T);
for(int ii=;ii<=T;++ii)
{
scanf("%d%d%d%d%d",&n,&k,&x,&m,&s);
n++;
for(int i=;i<=n;++i)
first[i]=;
for(int i=;i<=m;++i)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
for(int i=;i<=k;++i)
{
add(i,n,x);
add(n,i,);
}
for(int i=;i<=n;++i)
dis[i]=INF;
for(int i=;i<=n;++i)
vis[i]=;
dijistra();
for(int i=;i<n;++i)
printf("%lld ",dis[i]);
printf("\n");
}
return ;
}

最短路(模板)【CodeChef CLIQUED,洛谷P3371】的更多相关文章

  1. 第K短路模板【POJ2449 / 洛谷2483 / BZOJ1975 / HDU6181】

    1.到底如何求k短路的? 我们考虑,要求k短路,要先求出最短路/次短路/第三短路……/第(k-1)短路,然后访问到第k短路. 接下来的方法就是如此操作的. 2.f(x)的意义? 我们得到的f(x)更小 ...

  2. 最小生成树 & 洛谷P3366【模板】最小生成树 & 洛谷P2820 局域网

    嗯... 理解生成树的概念: 在一幅图中将所有n个点连接起来的n-1条边所形成的树. 最小生成树: 边权之和最小的生成树. 最小瓶颈生成树: 对于带权图,最大权值最小的生成树. 如何操作? 1.Pri ...

  3. AC自动机模板3【洛谷3796】

    AC自动机的第三个模板 其实,个人觉得,目前我写的这三个不同的模板完全是可以合并在一起求解的. 只是,在这两个无关联的OJ上,同一个AC自动机都可以完成的问题被拆成了三道题而已. 因此,代码只需要略加 ...

  4. 洛谷 P3371 【模板】单源最短路径

    P3371 [模板]单源最短路径 题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包含三个整数N.M.S,分别表示点的个数.有向边的个数.出 ...

  5. 洛谷 P3371 【模板】单源最短路径(弱化版) && dijkstra模板

    嗯... 题目链接:https://www.luogu.org/problem/P3371 没什么好说的,这是一个最短路的模板,这里用的dijkstra做的... 注意: 1.dijkstra和邻接表 ...

  6. 洛谷P3371 【模板】单源最短路径

    P3371 [模板]单源最短路径 282通过 1.1K提交 题目提供者HansBug 标签 难度普及/提高- 提交  讨论  题解 最新讨论 不萌也是新,老司机求带 求看,spfa跑模板40分 为什么 ...

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

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

  8. 单源最短路径spfa模板(pascal)洛谷P3371

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

  9. 最短路径Dijkstra算法模板题---洛谷P3371 【模板】单源最短路径(弱化版)

    题目背景 本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 P4779. 题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入格式 第一行 ...

随机推荐

  1. 【ABAP系列】SAP ABAP 运算符

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP 运算符   前 ...

  2. 关于Unity3D中的SerialField这个Attribute的功能

    首先我们看看效果,以下是源文件的内容: 然后对应的面板: 要注意的地方其实就这里: 可以看出,public默认就可以在面板中进行修改,相应的设为private的isCreateSoldier却不会出现 ...

  3. UUID工具类及使用

    1.工具类: package UUIdtest; import java.util.UUID; public class UUIDUtil { public static String getUUID ...

  4. 获取IP地址的几种方法

    根据ip获取地址的几种方法 1.调用新浪IP地址库 <script type="text/javascript" src="js/jquery.js"&g ...

  5. [LeetCode] 164. 最大间距

    题目链接 : https://leetcode-cn.com/problems/maximum-gap/ 题目描述: 给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值. 如果数组元素个数 ...

  6. offsetWidth clientWidth scrollWidth 的区别

    了解 offsetWidth clientWidth scrollWidth 的区别 最近需要清除区分开元素的width,height及相应的坐标等,当前这篇用来区分offsetWidth clien ...

  7. Datatable 中的数据查询(查询不重复记录)

    http://blog.csdn.net/lovexiaoxiao/article/details/3734932 //在sql中我们使用distinct查询不重复记录    //然而我在项目中表关系 ...

  8. python之 yield --- “协程”

    在编程中我们经常会用到列表,以前使用列表时需要声明和初始化,在数据量比较大的时候也需要把列表完整生产出来,例如要存放1000给数据,需要准备长度1000的列表,这样计算机就需要准备内存放置这个列表,在 ...

  9. 测试员小白必经之路----常见的Dos命令

    Dos是什么? 是一个命令行执行的操作系统 进入终端: win + r 运行输入: cmd 当前计算机的本地时间:Time 退出当前正在执行的命令: ctrl +c 设置在多少时间后自动关机: Shu ...

  10. VMware Workstation key

    VMware workstation 11 Pro key VY790-6FF9M-H8D3Q-1PY5T-YFUTD AA5M8-8NGD3-M805Y-K5Q7G-X28E6 UY3TR-88W4 ...