最短路模板:dij,spfa与floyd

图论技能get!
一个超强大的建图网站

最短路问题

1.dij算法

用于单源最短路
仅适用于没有负边权的情况
初始化dis数组为inf,dis【起点】=0;
tool:priority-queue(按dis升序)
先把起点放进队列
每次取出排头now,枚举它能去的地方v;
如果——

dis[v]>dis[now]+p[i].w

说明目前从now走到v更优,就更新它,并入队
最后now出列,并永远不要回来(用人话说就是判重)

模板

void dij(){for(int i=1;i<=n;i++) dis[i]=INT_MAX;memset(jd,0,sizeof(jd));dis[s] = 0;priority_queue<pr,vector<pr>,greater<pr> >q;q.push(make_pair(0,s));int tot=0;while(!q.empty()){int now=q.top().second;q.pop();if(jd[now]) continue;jd[now]=1;for(int i=fi[now];~i;i=p[i].nxt){int v=p[i].to;//printf("#%d %d %d\n",p[i].nxt,now,v);if(dis[v]>dis[now]+p[i].w){dis[v]=dis[now]+p[i].w;q.push(make_pair(dis[v],v)); }}}
}

(关于链式前向星存图,请移步这里

证明

因为没有负权
所以当前dis最小的值以后不可能从别的地方再更新
所以每次都取最小的,每个就只需取一次(n)

备注

因为优先队列操作复杂度带个log,所以
总复杂度为:O(nlogn)

从证明也可以看出,dij只适用于正权,那么有负权是怎么办?
可以使用——

2.SPFA

“spfa已经死了”
和dij其实很类似,只是他不用优先队列,也不判重,只要枚举出度满足上面那个关系式就可以进队(当然,已经在的不要再进了)
当队列为空结束

代码

void spfa(double x){queue<int>q;mem(jd,1);for(int i=1;i<=n;i++) dis[i]=(double)inf;mem(nm,0);for(int i=0;i<m;i++){p[i].w -= x;}for(int i=1;i<=n;i++){q.push(i);}while(!q.empty()){int now=q.front();q.pop();jd[now]=0;for(int i=fi[now];~i;i=p[i].nxt){int v=p[i].to;if(dis[v]>=dis[now]+p[i].w){dis[v]=dis[now]+p[i].w;if(jd[v]==0) q.push(v);}}}for(int i=0;i<m;i++) p[i].w +=x;return;
}

证明

因为不去重,队列还是空了,说明已经没有任何两对满足更新的关系式~~(暴力有什么好证明的)~~

备注

复杂度十分 玄学 不稳定
在特殊构造和稠密图可能卡成O(mn)
直接裂开(2018NOIP血的教训)
所以尽量还是用dij吧

floyd

多源!!!!
代码《过于冗长》,直接看着代码解释吧。。。

代码

for(int k = 1; k <= n; ++k)for(int i = 1; i <= n; ++i)for(int j = 1; j <= n; ++j)dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);

证明

(想不明白直接背)
dp[i][j][k]是从i到j经过中转编号最大值为k的最短路
那么dp[i][j][k]更新到dp[i][j][k+1]就是看看经过k+1会不会更优呗
所以就是上面那个状态转移方程
最后dp[i][j][n]就是最终的最短路

踩蛋

(这个不是王建国写的)

负环

如果存在一个总权值为负值的环,那么所有能碰到该环的两点的最短路都会是无穷小(大风车吱吖吱悠悠的转
此时spfa就会出现死循环
所以需要特殊判断负环
如果一条路径经过的点大于n,显然它是经过了环
而你算着算着最短路它为啥溜号去跑环了呢?一定是出现了负环
从而进行判断
关于代码实现,我们可以在更新时加一行转移:

nm[v]=nm[now]+1

代码

bool spfa(){queue<int>q;mem(jd,0);for(int i=1;i<=n;i++) dis[i]=inf;mem(nm,0);q.push(1);jd[1]=1;dis[1]=0;while(!q.empty()){int now=q.front();q.pop();jd[now]=0;for(int i=fi[now];~i;i=p[i].nxt){int v=p[i].to;if(dis[v]>dis[now]+p[i].w){dis[v]=dis[now]+p[i].w;nm[v]=nm[now]+1;if(jd[v]==0) q.push(v);if(nm[v]>=n){return true;}}}}return false;
}

觉得明白了可以来洛谷水道模板

就酱!拜拜~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/318784.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P5748-集合划分计数【EGF,多项式exp】

正题 题目链接:https://www.luogu.com.cn/problem/P5748 题目大意 求将nnn的排列分成若干个无序非空集合的方案。 输出答案对998244353998244353998244353取模。 1≤n≤105,1≤T≤10001\leq n\leq 10^5,1\leq T\leq 10001≤n≤105,1≤T≤1000 解题思路 就是求划分数 分成ii…

牛客题霸 [ 岛屿数量] C++题解/答案

牛客题霸 [ 岛屿数量] C题解/答案 题目描述 给一个01矩阵&#xff0c;1代表是陆地&#xff0c;0代表海洋&#xff0c; 如果两个1相邻&#xff0c;那么这两个1属于同一个岛。我们只考虑上下左右为相邻。 岛屿: 相邻陆地可以组成一个岛屿&#xff08;相邻:上下左右&#xff09;…

ASP.NET Core 实战:将 .NET Core 2.0 项目升级到 .NET Core 2.1

一、前言最近一两个星期&#xff0c;加班&#xff0c;然后回去后弄自己的博客&#xff0c;把自己的电脑从 Windows 10 改到 Ubuntu 18.10 又弄回 Windows 10&#xff0c;原本计划的学习 Vue 中生命周期的相关知识目前也没有任何的进展&#xff0c;嗯&#xff0c;罪过罪过。看了…

图论:dij算法优化:双端队列及详细证明

dij原来的写法请移步这里 首先&#xff0c;让我们举一个洛谷中的情境 这题中&#xff0c;我们可以二分mid答案&#xff0c;小于等于mid的边权是0&#xff0c;大于的是1&#xff0c;再计算最短路是否<k&#xff1b; 那么在这样边权只有0和1的时候&#xff0c;dij算法是否可以…

2021牛客暑期多校训练营4 B-Sample Game(概率DP)

B-Sample Game ding_ning123大佬题解 注&#xff1a;上述题解图片来自ding_ning123大佬题解 Code #include<bits/stdc.h> using namespace std; using lllong long; template <class Tint> T rd() {T res0;T fg1;char chgetchar();while(!isdigit(ch)) {if(ch-…

P6775-[NOI2020]制作菜品【贪心,dp】

正题 题目链接:https://www.luogu.com.cn/problem/P6775 题目大意 nnn种原材料&#xff0c;第iii个有did_idi​个&#xff0c;mmm道菜品都需要kkk个原料而且每道菜最多只能用两种材料。 要求构造方案使得满足条件。 1≤n≤500,n−2≤m≤5000,1≤k≤5000,(∑i1ndi)mk1\leq n\l…

牛客题霸 [螺旋矩阵] C++题解/答案

牛客题霸 [螺旋矩阵] C题解/答案 题目描述 给定一个m x n大小的矩阵&#xff08;m行&#xff0c;n列&#xff09;&#xff0c;按螺旋的顺序返回矩阵中的所有元素。 题解&#xff1a; 其实就是模拟过程&#xff0c;先往左走&#xff0c;走到头向下走&#xff0c;到头后向左走…

递推:Ybtoj: D.4 序列个数

传送门 这题需要使用数形结合的思想 用一个矩形表示序列&#xff0c;若(i&#xff0c;j)点为1&#xff0c;表示第i个数是j 比如&#xff1a; 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 表示的序列是&#xff1a;41235 显然每行和每列都只能有一个1 回到本题&#xf…

codeforces280 C. Game on Tree(期望)

C. Game on Tree 单独考虑每个点对答案的贡献。 删除一个点的方案是删除它或者它的祖先&#xff0c;那么对答案的贡献是1depu\frac 1 {\text{dep}_u}depu​1​ #include<cstdio> #include<vector>int n; std::vector<int> g[100005]; int dep[100005]; vo…

OrchardCore 如何实现模块化( Modular )和 Multi-Tenancy

一、概述通常我们会在 Startup 类通过 void ConfigureServices(IServiceCollection services) 配置应用的服务。常见的形如 AddXXX 的方法&#xff0c;实际上调用的都是 IServiceCollection 或直接说是 ServiceCollection 的 AddSingleton 等方法。调用ApplicationBuilder 的 R…

P2350-[HAOI2012]外星人【线性筛】

正题 题目链接:https://www.luogu.com.cn/problem/P2350 题目大意 给出NNN质因数分解之后的结果&#xff0c;求每次Nφ(N)N\varphi(N)Nφ(N)&#xff0c;多少次后N1N1N1。 N∏i1mpiqi,1≤m≤2000,1≤pi≤105,1≤qi≤109N\prod_{i1}^mp_i^{q_i},1\leq m\leq 2000,1\leq p_i\le…

牛客题霸 [ 最长回文子串] C++题解/答案

牛客题霸 [ 最长回文子串] C题解/答案 题目描述 对于一个字符串&#xff0c;请设计一个高效算法&#xff0c;计算其中最长回文子串的长度。 给定字符串A以及它的长度n&#xff0c;请返回最长回文子串的长度。 题解&#xff1a; 两个方法&#xff1a; 一个是经典暴力&#…

强连通分量:洛谷P3387 模板:缩点

传送门 顾名思义&#xff0c;模板awa #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <string> #include <queue> #include <vector> #define ll long long usi…

2021牛客暑期多校训练营4 E-Tree Xor(异或+思维+区间交 or Trie树)

E-Tree Xor 首先不考虑区间限制条件&#xff0c;我们给定其中一个点的权值后&#xff0c;那么其他点的权值也就确定。比如 val10\text{val}_10val1​0&#xff0c;即可通过变得限制求出其他点valu\text{val}_uvalu​&#xff0c;而且不难发现如果val10⊕a\text{val}_10\oplus …

【.NET Core项目实战-统一认证平台】第八章 授权篇-IdentityServer4源码分析

上篇文章我介绍了如何在网关上实现客户端自定义限流功能&#xff0c;基本完成了关于网关的一些自定义扩展需求&#xff0c;后面几篇将介绍基于IdentityServer4&#xff08;后面简称Ids4&#xff09;的认证相关知识&#xff0c;在具体介绍ids4实现我们统一认证的相关功能前&…

[科技]Loj#6564-最长公共子序列【bitset】

正题 题目链接:https://loj.ac/p/6564 题目大意 给两个序列a,ba,ba,b求它们的最长公共子序列。 1≤n,m,ai,bi≤71041\leq n,m,a_i,b_i\leq 7\times 10^41≤n,m,ai​,bi​≤7104 解题思路 无意间看到的一个bitsetbitsetbitset科技。 首先设fi,jf_{i,j}fi,j​表示aaa串匹配到…

牛客题霸 [找到字符串的最长无重复字符子串] C++题解/答案

牛客题霸 [找到字符串的最长无重复字符子串] C题解/答案 题目描述 给定一个数组arr&#xff0c;返回arr的最长无的重复子串的长度(无重复指的是所有数字都不相同)。 题解&#xff1a; i和j两个指针分别指不重复子串的两端&#xff0c;根据情况各自移动&#xff0c;记录最大…

并查集:P1196 [NOI2002] 银河英雄传说

传送门 带权并查集最棒了 dep记录深度&#xff0c;size记录集合大小 转移见代码 #include<cstdio> #include<algorithm> #include<iostream> using namespace std; const int N31000; int n,m; int t; int dep[N],fa[N],size[N]; char s; int a,b; int find…

2021牛客暑期多校训练营4 D-Rebuild Tree(prufer序列+树形dp)

D-Rebuild Tree Prufer 是这样建立的&#xff1a;每次选择一个编号最小的叶结点并删掉它&#xff0c;然后在序列中记录下它连接到的那个结点。重复n−2n-2n−2次后就只剩下两个结点&#xff0c;算法结束。&#xff08;为什么不是n−1n-1n−1次呢&#xff1f;因为第n−1n-1n−1…

牛客题霸 [ 求二叉树的层序遍历] C++题解/答案

牛客题霸 [ 求二叉树的层序遍历] C题解/答案 题目描述 给定一个二叉树&#xff0c;返回该二叉树层序遍历的结果&#xff0c;&#xff08;从左到右&#xff0c;一层一层地遍历&#xff09; 例如&#xff1a; 给定的二叉树是{3,9,20,#,#,15,7}, 该二叉树层序遍历的结果是 [ [3…