【模板】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)必 ...
随机推荐
- Mybatis源码学习之类型转换(四)
简述 JDBC数据类型与Java语言中的数据类型并不是完全对应的,所以在PreparedStatement为SQL语句绑定参数时,需要从Java类型转换成JDBC类型,而从结果集中获取数据时,则需要从 ...
- 牛券Cow Coupons
USACO12FEB 久违的奶牛题. 题意: FJ准备买一些新奶牛,市场上有 $ N $ 头奶牛 $ (1 \leq N \leq 50000) $ ,第i头奶牛价格为 $ P_i (1 \leq P ...
- Java中基本数据类型
在数据类型中,最常用也是最基础的数据类型,被称作基本数据类型.可以使用这些类型的值来代表一些简单的状态. Java 语言的基本数据类型总共有以下8 种,下面是按照用途划分出的4 个类别: 定点类型: ...
- MAC ADDRESS
可以使用手机Wifi或蓝牙的MAC地址作为设备标识,但是并不推荐这么做,原因有以下两点:硬件限制:并不是所有的设备都有Wifi和蓝牙硬件,硬件不存在自然也就得不到这一信息.获取的限制:如果Wifi没有 ...
- Nginx-HTTP之listen指令解析
1. ngx_http_core_listen static char * ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void ...
- LeetCode 复原IP地址(探索字节跳动)
题目描述 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式. 示例: 输入: "25525511135" 输出: ["255.255.11.135&qu ...
- article收藏
sca https://github.com/spring-cloud-incubator/spring-cloud-alibaba spring-cloud-document https://git ...
- 解决ssh连接超时(ssh timeout)的方法
echo export TMOUT=1000000 >> /root/.bash_profile (可设置为-1为永不超时) cat /root/.bash_profile source ...
- PackageUtils
import android.content.Context; import android.content.Intent; import android.content.pm.Application ...
- [Java复习] 多线程&并发 知识点补充
0. wait/notify/notifyAll的理解? wait:让持有该对象锁的线程等待: notify: 唤醒任何一个持有该对象锁的线程: notifyAll: 唤醒所有持有该对象锁的线程: 它 ...