首页 > 其他分享 >「学习笔记」重修最短路

「学习笔记」重修最短路

时间:2023-04-28 21:56:11浏览次数:29  
标签:mathbf int 短路 重修 笔记 算法 复杂度 dis

\(u\) 到 \(v\) 的最短路径的长度就是 \(u\) 到 \(v\) 的最短路。
单源最短路算法可以求出一个点到其他点的最短路。
全源最短路算法可以求出每一个点到其他各点的最短路。
松弛操作:dis[v] = min(dis[v], dis[u] + w);

算法

Floyd 算法

全源最短路算法,时间复杂度 \(O_{n^3}\),空间复杂度 \(O_{n^2}\),用了 DP 的思想。

实现

设数组 f[x][y],含义:\(x\) 到 \(y\) 的最短路。
转移:f[x][y] = min(f[x][y], f[x][k] + f[k][y]);
\(k\) 为除了 \(x\) 和 \(y\) 的其他节点。

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

dijkstra 算法

单源最短路算法,时间复杂度 \(O_{n^2}\),运用了贪心的思想。

实现

将点分为两部分,已经确定最短路的点和没确定最短路的点,记已确定最短路的点的集合为 \(\mathbf{S}\),未确定最短路的点的集合为 \(\mathbf{T}\)。
设 \(s\) 为起点,初始时设 dis[s] = 0,其他节点的 dis 设为 \(\inf\)。
从 \(\mathbf{T}\) 中取一个最短路最小的点,将它转移到 \(\mathbf{S}\) 集合去,并用它来更新其他点的最短路,重复此操作,直到 \(\mathbf{T}\) 为空。

这里用最短路最小点的来更新答案就是运用了贪心的思想。

int n;
int dis[N], vis[N];
vector<pair<int, int> > son[N];

void dij(int s) {
	for (int i = 0; i <= n; ++ i) {
		dis[i] = inf;
	}
	dis[s] = 0;
	for (int i = 1; i < n; ++ i) {
		int u = 0, minn = inf;
		for (int j = 1; j <= n; ++ j) {
			if (vis[j] || dis[j] >= minn)	continue;
			u = j;
			minn = dis[j];
		}
		vis[u] = true;
		for (auto it : son[u]) {
			int v = it.first, w = it.second;
			dis[v] = min(dis[v], dis[u] + w);
		}
	}
}

优化

我们每次从剩下的元素中取最小的,进行 \(n\) 次,复杂度为 \(O_{n \log n}\),但是,我们可以用小根堆堆来使得这步操作的时间复杂度降低至 \(O_{n \log n}\),于是,就有了 dijkstra 的堆优化版本。

typedef pair<int, ll> pil;

void dij(int st) {
	priority_queue<pil, vector<pil>, greater<pil> > q;
	for (int i = 1; i <= n; ++i) {
		dis[i] = 1e9;
		vis[i] = 0;
	}
	dis[st] = 0;
	q.push(make_pair(0, st));
	while (!q.empty()) {
		int u = q.top().second;
		q.pop();
		if (vis[u])	continue;
		vis[u] = 1;
		for (int i = h[u]; i; i = e[i].nxt) {
			int v = e[i].v;
			if (dis[v] > dis[u] + e[i].w) {
				dis[v] = dis[u] + e[i].w;
				q.push(make_pair(dis[v], v));
			}
		}
	}
}

不管是朴素版本的 dijkstra,还是堆优化版本的 dijkstra,都要求图的边权不为负边权。

Bellman-Ford 算法

这个算法或许有些人没听说过,但是它的优化版本你肯定听过,SPFA。
单源最短路算法,时间复杂度 \(O_{nm}\)

实现

每一次松弛操作都会产生一条最短路,如果一个图中不存在负环,最多会松驰 \(n - 1\) 次。

for (int i = 1; i <= n; ++ i) {
	dis[i] = inf;
}
dis[s] = 0;
for (int i = 1; i <= n; ++ i) {
	for (int j = 1; j <= m; ++ j) {
		dis[v[j]] = min(dis[v[j]], dis[u[j]] + w[j]);
	}
}

SPFA 算法

关于SPFA,它。。。
SPFA算法是 Bellman-Ford 算法的队列优化版本,最坏时间复杂度为 \(O_{nm}\),一般跑得很快。

实现

给原先的 Bellman-Ford 加一个队列即可。

void spfa(int s) {
	queue<int> q;
	for (int i = 1; i <= n; ++ i) {
		dis[i] = inf;
		vis[i] = 0;
	}
	dis[s] = 0;
	q.push(s);
	vis[s] = 1;
	while (!q.empty()) {
		int u = q.front();
		q.pop();
		vis[u] = 0;
		for (auto it : son[u]) { 
			int v = it.first, w = it.second; 
			if (dis[v] > dis[u] + w) {
				dis[v] = dis[u] + w;
				if (! vis[v]) {
					q.push(v);
					vis[v] = 1;
				}
			}
		}
	}
}

标签:mathbf,int,短路,重修,笔记,算法,复杂度,dis
From: https://www.cnblogs.com/yifan0305/p/17363015.html

相关文章

  • [笔记] ELMO, BERT, GPT 简单讲解 - 李宏毅
    国内视频地址:https://www.bilibili.com/video/BV17441137fa/?spm_id_from=333.880.my_history.page.click&vd_source=bda72e785d42f592b8a2dc6c2aad24091NLP基础1.1词的表示过程演进:one-hot编码词袋模型wordembedding1.2multiplesense1)明确两个概念:token和ty......
  • 李宏毅self-attention笔记
     面对的问题是什么?复杂输入,多个变长的向量这里自然会想到RNN,后面会有比较具体的场景,可以是一段话,每个word一个向量,可以用onehot,但大多时候是用embedding可以是一段印频,每25ms一个向量,按10ms滑动,可以看出音频的数据量是非常大的也可以是一张图片。。。输出当然有多种形......
  • 百炼成仙阅读笔记
    第二章字符串只要不为空,就代表真,否则代表假。数字只要不为0,就代表真,否则就是假split("")把字符串分开为数组toString().lengthstr.indexOf("")搜索返回位置replace("a","A")第三章jQuery基础css选择器5种:标签(div)、ID(#a)、类class(.a)、群组(.a,.b,.c)、后代(.a.b)<in......
  • 《大话数据结构》读书笔记 附PDF #C3
    刚刚读完了《大话数据结构》,这本书真的是一本不错的入门级别的数据结构和算法的教材。首先,作者通过幽默的语言和丰富的图示,使得枯燥的数据结构与算法变得生动有趣。在阅读过程中,我感受到了作者对于知识点深入浅出的讲解,即使是像我这样初学者也能够轻松理解。其次,书中的配套练习......
  • 构建之法 阅读笔记04
    第十一章软件设计与实现11.2图形建模和分析方法思维导图、实体关系图、UseCaseDiagram11.3其他设计方法形式化的方法、文学化编程11.5开发阶段的日常管理第十二章用户体验12.1用户体验的要素用户的第一印象从用户的角度考虑问题软件服务始终都要记住用户的选择(......
  • 《代码大全2》阅读笔记01
    在我的软件开发经历中,我曾经遇到过编写代码时犯的一些错误,而这些错误在《代码大全2》这本书中都有提到。其中一个问题是过度地注释代码。我过去常常使用很多注释,认为它们可以帮助我自己和其他人更好地理解代码。但是,在阅读这本书之后,我了解到这种做法可能会带来一些负面影响,并会......
  • 读书笔记-《人件集》-3
    《人件集》是由TomDeMarco于1978年撰写的一部关于软件开发项目管理的著作。该书的主要观点是,成功的软件开发项目需要考虑到人因素,即处理好项目中的人员关系、个人动机以及人员互动等等。以下是该书的大纲概述:第一部分:绪论1.软件开发的难点2.软件开发管理3.人因素第二部分:管......
  • 工具适配新系统平台笔记
    适配过程中需要安装的东西(包括但不限于):yuminstall-ygcc-c++yuminstall-yboost-develyuminstall-ylibaio-devel适配过程遇到的问题:默认snappy版本较新(使用了c++11的语法),gcc编译器无法编译(指定了-std=gnu++98)解决方法:将snappy1.1.7版本的devel和lib的rpm(老版本)......
  • pwn刷题笔记(整数溢出)
    [BJDCTF2nd]r2t3写出反汇编代码如下:intds:__bss_start;intmain(){charbuf[0x408-4]intvar[4];my_init();puts("**********************************");puts("*WelcometotheBJDCTF!*");puts("[+]Ret......
  • Java学习笔记(六)
    1、什么是JavaBean类是公共的有一个无参的公共的构造器有属性,且有对应的get、set方法  2、对单例模式的理解单例模式分为两种: 这种方式叫做饿汉式,是在类加载的时候就直接将对象创建了出来。还有一种懒汉式 懒汉式是在用到实例对象的时候才会将对象创建出来。但......