基础图算法
Dijkstra求最短路 ( 堆优化O(m*logn) ):
就是对朴素版dijkstra使用最小堆优化。
- 起点的距离初始化为零,其他点初始化成无穷大。
- 建立一个数组st,标记是否访问过,防止重复访问某个点
- 将起点放入堆中。
- 不断循环,直到堆空。每一次循环中执行的操作为:
1.弹出堆顶(堆中最小的边权),同时标记已访问(若访问过就跳过该点)。
2.用该点更新临界点的距离,若更新成功就加入到堆中。
spfa求最短路 ( 平均O(m), 最坏O(nm) ):
- 建立一个队列q,初始时队列里只有起始点。
- 用数组dis记录起始点到所有点的最短路径(起点的距离初始化为零,其他点初始化成无穷大。
- 建立一个数组st,标记点是否在队列中。
- 取出队头并出队,如果 起点经过队头到其他点变短且被点不在队列中,则把该点加入队。
- 重复执行直到队列为空。
- 在保存最短路径的数组中,就得到了最短路径。
spfa判断负环 ( 平均O(m), 最坏O(nm) ):
如果一个点在被入队次数大于 n 次,说明存在负环。
- 防止漏找要把所有的点入队,并用数组st 标记全部已入队。
- 用数组dis记录更新某个起点到当前点的最短路径,
- 如果 通过当前顶点
u到 下个节点j的路径比当前已知路径更短,更新dis[j]- 取出队头并出队,不断更新直至队列为空
- 在更新时,用数组cnt记录每个点更新的次数,如果更新次数大于n,那便存在负环
- 如若队列为空时也不存在更新次数大于n的点,那便不存在负环
注:1.dis数组可不必初始化,若存在负环,每个点的路径必为负无穷,且初始值0大于负无穷,所以一定会把这些距离为负无穷的点不断更新。
2.当数据交大时,经验上 可用
栈代替队列,同时也可以特判更新次数超过某个值提前确定存在负环
Prim求最小生成树 ( 堆优化O(m*logn) ):
与 Dijkstra 思路相似,用点构建最小生成树
- 起点的距离初始化为零,其他点初始化成无穷大。
- 用一个计数器
cnt记录已访问点的数量,建立一个数组st,标记是否访问过 (防止重复访问某个点)- 将起点放入堆中。
- 不断循环,直到 cnt == 点的总数。每一次循环中执行的操作为:
1.弹出堆顶(堆中最小的边权)
2.标记已访问(若访问过就跳过该点),同时 cnt++
3.用该点更新临界点的距离,若更新成功就加入到堆中。
Kruskal求最小生成树 ( O(m*logn) ):
用边构建最小生成树
- 建立一个结构体,内容包含:a->b 的值为 c
- 将结构体按照权值的大小进行升序排序,然后从小到大逐个遍历判断。
- 如果这个边与之前选择的所有边不在一个集合,就将这条边选进集合;反之,舍去。
- 直到具有
n个顶点的连通网在集合中筛选出来n-1条边为止,若筛不满n-1条边说明不存在最小生成树
注:判断是否在一个集合可用 并查集
拓扑排序算法 ( O(n+m) ):
- 建立一个队列q ,把图中所有入度为
0的点入队- 当队列非空时,重复执行以下操作:
- 取出队头记录为点
u,并出队- 遍历所有与点
u相邻的顶点v,执行:
- 将
v的入度-1(删除边u ->v), 若v的入度变为0,则将v入队

浙公网安备 33010602011771号