【模板】dijkstra与floyd
(我永远喜欢floyd)
温馨提示:与SPFA一起食用效果更佳
传送门:https://www.cnblogs.com/Daz-Os0619/p/11388157.html
Floyd
大概思路:
对于某两个点来说,查找他们之间是否连通,若连通,是记录他们间的最短路。
这里的最短路有两个方向:一个是直接到,一个是通过另外一个点到。(十分单纯的最短路了)
不需要多讲上代码!
void floyd() {
for (int k = ; k <= n; ++k)
for (int i = ; i <= n; ++i)
for (int j = ; j <= n; ++j)
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
Dijkstra
大概思路:
(跟SPFA差不多??)
有一个集合P,一开始只有源点S在P中,每次更新都把集合之外路径值最小的一个放入集合中,更新与它相连的点,重复前面的操作直到集合外没有元素。
特殊要求:所有边权要是正的
这时的时间复杂度为O(n*n) (比较危险)
可以采用堆来优化 时间复杂度O(n*logn)
(蒟蒻发言:怎么用堆优化?)
堆
一颗完全二叉树。
这里用到的小根堆是最小值作为堆顶元素,大根堆反之。
大概长下面这样:
利用小根堆优化Dijkstra的理由与用SLF优化SPFA的理由相同,核心思想也相近,但是写法差异很大。
核心思想:因为每一次都会从队首开始遍历,当队首是最小值时,被更新的所以节点的值也会是最小值,这样可以节省很大一部分时间。
(这里就体现优先队列的好处)
下面是核心代码(可以先看注释,后面有图解):
struct edges {
int next, to, v;
edges() {}
edges(int _n, int _t, int _v) : next(_n), to(_t), v(_v) {}//next表示与这条边同起点的上一条边
} e[]; struct heap_node {
int v, to;
heap_node() {}
heap_node(int _v, int _to) : v(_v), to(_to) {}
};
inline bool operator < (const heap_node &a, const heap_node &b) {
return a.v > b.v; //这里实现的是小根堆,如果要大根堆,把 > 改成 < 即可
} priority_queue <heap_node> h; inline void add_to_heap(const int p) {
for (int x = first[p]; x; x = e[x].next)//first表示以first为头的最后一条边
if (dis[e[x].to] == -)//如果下一条边还没在堆里
h.push(heap_node(e[x].v + dis[p], e[x].to));//加上前一个点的最短路值(跟新),放入堆
} void Dijkstra(int S) {
memset(dis, -, sizeof(dis));//清空(便于将数据放入堆里)
while (!h.empty()) h.pop();//清空堆
dis[S] = , add_to_heap(S);//现将所有与源点相连的点放入堆中
int p;
while (!h.empty()) { //堆空时所有的点都更新完毕(与SPFA相反)
if (dis[h.top().to] != -)//如果与堆顶元素相连的点已经有了最短路值
{
h.pop();//弹掉堆顶 (此时堆顶不会被更新了)
continue;//一直找到可以被更新的点
}
p = h.top().to;//找到与堆顶相连且不在堆里的点
dis[p] = h.top().v;//更新最短路值(只是堆顶的)
h.pop();//弹掉
add_to_heap(p);//再更新与它相连的点,并将与它相连的点放入堆
}
}
好长的注释啊。。
再画个图解释一下
(这里的样例和SPFA的样例一样)
后面就这样一直循环直到队列为空。为空时所有最短路更新完毕。
完整代码:
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
struct edge
{
int next,to,v;
edge(){}
edge(int a,int b,int c)
{
next=a;
to=b;
v=c;
}
}E[];
int first[],n,dis[];
int S;
struct heap
{
int to,v;
heap(){}
heap(int a,int b)
{
to=a;
v=b;
}
};
inline bool operator< (const heap &a,const heap &b)
{
return a.v>b.v;
}
priority_queue<heap> h; void add_to_heap(int p)
{
for(int i=first[p];i;i=E[i].next)
{
if(dis[E[i].to]==-)
h.push(heap(E[i].to,dis[p]+E[i].v));
}
}
int tot;
void add_edges(int a,int b,int c)
{
E[++tot]=edge(first[a],b,c);
first[a]=tot;
}
void dijkstra(int S)
{
while(!h.empty())
h.pop();
memset(dis,-,sizeof(dis));
dis[S]=;
add_to_heap(S);
int p;
while(!h.empty())
{
if(dis[h.top().to]!=-)
{
h.pop();
continue;
}
p=h.top().to;
dis[p]=h.top().v;
h.pop();
add_to_heap(p);
}
}
int m;
int main()
{
cin>>n>>m>>S;
int A,B,C;
for(int i=;i<=m;i++)
{
cin>>A>>B>>C;
add_edges(A,B,C);
}
dijkstra(S);
for(int i=;i<=n;i++)
cout<<dis[i]<<endl;
return ;
}
结束!
今天也想放烟花!
【模板】dijkstra与floyd的更多相关文章
- (最短路径算法整理)dijkstra、floyd、bellman-ford、spfa算法模板的整理与介绍
这一篇博客以一些OJ上的题目为载体.整理一下最短路径算法.会陆续的更新... 一.多源最短路算法--floyd算法 floyd算法主要用于求随意两点间的最短路径.也成最短最短路径问题. 核心代码: / ...
- 最短路(Dijkstra,Floyd,Bellman_Ford,SPFA)
当然,这篇文章是借鉴大佬的... 最短路算法大约来说就是有4种——Dijkstra,Floyd,Bellman_Ford,SPFA 接下来,就可以一一看一下... 1.Dijkstra(权值非负,适用 ...
- 算法学习笔记(三) 最短路 Dijkstra 和 Floyd 算法
图论中一个经典问题就是求最短路.最为基础和最为经典的算法莫过于 Dijkstra 和 Floyd 算法,一个是贪心算法,一个是动态规划.这也是算法中的两大经典代表.用一个简单图在纸上一步一步演算,也是 ...
- 几个小模板:topology, dijkstra, spfa, floyd, kruskal, prim
1.topology: #include <fstream> #include <iostream> #include <algorithm> #include & ...
- dijkstra,bellman-ford,floyd分析比较
http://www.cnblogs.com/mengxm-lincf/archive/2012/02/11/2346288.html 其实我一直存在疑惑是什么导致dijkstra不能处理负权图? 今 ...
- hdu 1874 畅通工程续(模板题 spfa floyd)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1874 spfa 模板 #include<iostream> #include<stdio ...
- 最短路 dijkstra and floyd
二:最短路算法分析报告 背景 最短路问题(short-path problem):若网络中的每条边都有一个数值(长度.成本.时间等),则找出两节点(通常是源节点和阱节点)之间总权和最小的路径就是最短路 ...
- 最短路知识点总结(Dijkstra,Floyd,SPFA,Bellman-Ford)
Dijkstra算法: 解决的问题: 带权重的有向图上单源最短路径问题.且权重都为非负值.如果采用的实现方法合适,Dijkstra运行时间要低于Bellman-Ford算法. 思路: 如果存在一条从i ...
- Algorithm --> Dijkstra和Floyd最短路径算法
Dijkstra算法 一.最短路径的最优子结构性质 该性质描述为:如果P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,k和s是这条路径上的一个中间顶点,那么P(k,s)必 ...
随机推荐
- Java的23种设计模式 <二>
1.单例模式(Singleton Pattern) 定义:Ensure a class has only one instance, and provide a global point of acc ...
- Python相关分析—一个金融场景的案例实操
哲学告诉我们:世界是一个普遍联系的有机整体,现象之间客观上存在着某种有机联系,一种现象的发展变化,必然受与之关联的其他现象发展变化的制约与影响,在统计学中,这种依存关系可以分为相关关系和回归函数关系两 ...
- 一 、Linux基础命令及使用帮助
linux的哲学思想: 一切皆文件: 把几乎所有资源,包括硬件设备都组织为文件系统 由众多单一目的小程序组成:一个程序只实现一个功能,而且要做好 组合小程序完成复杂任务 尽量避免跟用户交互 目的:实现 ...
- Jmeter在一次进程中如何循环执行某个步骤
在使用Jmeret工具过程中比如我使用借款功能,如果想多借几次就需要一次次执行脚本,如果我在脚本执行过程中登陆一次,可以重复执行借款这一个操作那么就方便多了 于是就用到(循环控制器)这个功能 1.我需 ...
- 【sed】进阶
sed的基本用法已能满足大多数需求,但当需要时,知道这些高级特效的存在及如何使用将提供莫大的帮助! 1. 多行命令 sed编辑器提供三个用于处理多行文本的特殊命令: N:将数据 ...
- LeetCode 128. 最长连续序列(Longest Consecutive Sequence)
题目描述 给定一个未排序的整数数组,找出最长连续序列的长度. 要求算法的时间复杂度为 O(n). 示例: 输入: [100, 4, 200, 1, 3, 2] 输出: 4 解释: 最长连续序列是 [1 ...
- 之前有面试到两个日期的大小比较方式,现在整理一下几种方法。 例子: String beginTime=new String("2017-06-09 10:22:22"); String endTime=new String("2017-05-08 11:22:22"); 1 直接用Date自带方法before()和after()比较 SimpleDateFormat d
各种数据类型(日期/时间.integer.floating point和numeric)转换成格式化的字符串以及反过来从格式化的字符串转换成指定的数据类型.下面列出了这些函数,它们都遵循一个公共的调用 ...
- vacode查看已安装的插件
- Ubuntu16.04.3安装并配置samba方法
目的:单个Linux用户可以在windows电脑上通过映射网络驱动器的方式来访问自己的工作目录. 方法如下: 1.安装smb服务器:apt-get install samba2.安装smb支持的文件系 ...
- 一百一十三:CMS系统之前台注册界面
html {% from 'common/_macros.html' import static %}<!DOCTYPE html><html lang="en" ...