算法题-图论
图的表示
207.课程表
127.单词接龙
图的遍历
-
DFS
递归。。。
200.岛屿数量
239.矩阵中的最长递增路径 -
BFS
102.二叉树的层序遍历
看到最短,首先想到的是BFS
542.01矩阵
207.课程表
127.单词接龙
拓扑排序
对于一个有向无环图G进行拓扑排序,是将G中所有节点排成一个线性序列,该序列满足以下两个条件:① 每个节点有且仅出现一次 ② 若存在一条从节点A到节点B的路径,则在序列中A一定出现在B前面。
求一个有向无环图的拓扑排序步骤:
1.在图中找到一个没有前驱(入度为0)的节点,然后输出
2.从图中删除该节点和所有以它为起点的有向边 ( 使边到达的节点 v 的入度-1)
3.重复操作1和操作2,直到图为空 或 当前图不存在无前驱的顶点为止(图存在环)
210.课程表||
图的应用
最小生成树
最小生成树 (MST) 是 连接了图中所有节点且没有环,而且这些边的权值和最小
1584.连接所有点的最小费用
1631.最小体力消耗路径
-
普利姆Prim算法
将顶点分为两类,一类是树顶点(加入树里的顶点),一类是非树顶点(不在树里面的)。首先任选一个顶点加入树里,然后遍历每个树顶点到非树顶点的距离,选最短距离的那个非树顶点加入,然后重复这个过程,直到每个顶点都在树里。
-
克鲁斯卡尔Kruskal算法
首先按照边的权值进行从小到大开始排序,每次从剩余的边中选择权值较小的且边的两个顶点不在同一个集合(连在一起的顶点属于一个集合)内的边,加入到生成树,直到n-1条边为止。
- 并查集
并查集(Union-Find),又称不相交集合(Disjoint Set Union, DSU),是一种用于处理不相交集合的合并与查询问题的数据结构。它支持两种主要操作:
查找(Find):确定一个元素属于哪个集合。
合并(Union):将两个不同的集合合并成一个集合。
最短路径
- 迪杰斯特拉Dijkstra算法
单源最短路径,计算一个节点到其他所有节点的最短路径:
- 将所有的顶点分为两部分,也就是已知最短路程的顶点集合P和未知最短路径的顶点集合Q。最开始,已知最短路径的顶点集合P中只有源点一个顶点。我们这里用一个vis[ i ]数组来记录哪些点在集合P中,源点对应的是1,表示存在。用dis[i]数组记录源点到自己的最短距离,初始化为一个很大值,源点对应的是0。
- 在集合Q的所有顶点中选择一个离源点最近的顶点u(即dis[u]最小)加入到集合P。并考察所有以点u为起点的边,对每一条边进行松弛操作。例如存在一条从u到v的边,且v不在集合P中,那么可以通过将边u->v添加到尾部来拓展一条从s到v的路径,这条路径的长度是dis[u]+e[u][v]。如果这个值比目前已知的dis[v]的值要小,我们可以用新值来替代当前dis[v]中的值。
- 重复2过程,直到所有顶点添加到P中
743.网络延迟时间
-
弗洛伊德Floyd算法
多源最短路径 -
贝尔曼福特Bellman-Ford算法
- 用于求解单源、有负权边的最短路问题
- “求出从起点到终点不超过m条边构成的最短路径”
- 其优于Dijkstra的方面是边的权值可以为负数、实现简单,缺点是时间复杂度过高。时间复杂度是O(nm)
787. K 站中转内最便宜的航班
3.1 与迪杰斯特拉算法的区别:
- 迪杰斯特拉算法是借助贪心思想,每次选取一个未处理的最近的结点,去对与他相连接的边进行松弛操作;贝尔曼福特算法是直接对所有边进行N-1遍松弛操作
- 迪杰斯特拉算法要求边的权值不能是负数;贝尔曼福特算法边的权值可以为负数,并可检测负权回路
3.2 算法步骤
- 初始化:将起点到所有其他顶点的距离初始化为无穷大(INF),起点到自身的距离初始化为 0。
- 松弛操作:对图中的每一条边进行 V-1 次松弛操作(V 是图中顶点的数量)。松弛操作的定义是:对于边 (u, v),如果 distance[u] + weight(u, v) < distance[v],则更新 distance[v] = distance[u] + weight(u, v)。
- 检测负权环:再进行一次松弛操作,如果还能找到更短的路径,则说明图中存在负权环。
3.3 为什么对每一条边进行v-1次松弛操作,每个可到达的节点都可以得到最短路径?
在一个无负权环的图中,每次松弛操作相当于“尝试”通过当前边 (u, v) 缩短 v 的最短路径,最坏情况下,最多经过 v-1 次松弛,所有节点的最短路径一定会被找到。
3.4 为什么可以检测负权图?
如果图中没有负权环,经过 V-1 次松弛后,所有最短路径都已经确定,不会再被更新。
如果还能继续松弛,说明存在一个环,使得路径可以无限缩短(因为负权环的总权重为负,绕环越多,路径越短)。
3.5 怎么求出不超过m条边的最短路径
每次松弛操作相当于“尝试”通过当前边 (u, v) 缩短 v 的最短路径,假设a->b->c->d,三条边由最后往前依次给出,那么遍历三次,所有的顶点的最短路径才找到,要“求出从起点到终点不超过m条边构成的最短路径”,最多经过m次对所有边的松弛操作就可以找到 到终点不超过m条边构成的最短路径,再多一次 可能变成 超过m条的最短路径了。
3.6 优化SPFA算法
Bellman-Ford 的朴素实现是 O(VE),但实际中很多边不会被松弛。SPFA(Shortest Path Faster Algorithm) 是 Bellman-Ford 的优化版本,使用队列来只松弛那些可能被更新的顶点,平均时间复杂度可以接近 O(E),但在最坏情况下仍然是 O(VE)。