--- 这里是 cjiaw 的小窝(●'◡'●) ---

正在玩命加载中......

基础图算法

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的点入队
  • 当队列非空时,重复执行以下操作:
  1. 取出队头记录为点 u,并出队
  2. 遍历所有与点u相邻的顶点 v,执行:
  •  将v的入度-1(删除边u ->v), 若v的入度变为0,则将v入队

 

posted @ 2025-11-14 19:41  wwjjw  阅读(12)  评论(0)    收藏  举报