拓扑排序、Dijkstra、Prim/Kruskal、全部最短路径/传递闭包

拓扑排序:

应用于DAG图。先遍历一遍(DFS、BFS),每个节点标记入度(in-degree)。入度 为0的节点,放入一个队列。

初始时,该队列中的元素都是第一批的点(不依赖于任何其他元素);

之后,弹出该队列中所有元素,将其后继结点的入度减一,如果后继节点入度降为0,则放入该队列。

重复以上步骤,这样就分批次的标记上了依赖关系的排序。

单源最短路径Dijkstra:

是一个集合不断扩张和节点距离不断更新(减小)的过程,两个要点:如何更新节点的距离、如何选择下一个节点加入S。

初始时,集合S仅包含源点s,其他节点的到源点的距离Dist设为无穷。将当前节点curr设为s

之后,对当前节点s,如果s的某个邻居w不在S中(尚未访问),则尝试更新w的Dist

if w.Dist < curr.Dist + Dist(w, s); then

  w.Dist = curr.Dist = Dist(w, s);

之后,选择所有(s, w)中w.Dist最小的节点,作为下一次的curr节点,重复,直到S包含所有节点。

Prim/Kruskal,最小生成树问题

Prim算法从节点入手,初始时,集合S仅包含节点v0;S中节点的邻边放入一个最小堆heap。

之后,每次从堆中弹出当前最短的边e,如果另一端w还不在S中,则e将是最小生成树的一条边,然后w加入S,w的邻边加入堆heap

重复直到S包含所有的节点。

Kruskal算法从边入手,初始时,所有的节点作为一个集合都是孤立的,所有的边按照边长排序。

遍历已经排序的边,如果该边可以连接原来分离的两个子集,则这个边将是最小生成树对的一条边。

可以用一个并查集来维护各个集合的关系。

全部最短路径/传递闭包

也称Warshall算法,就是一个三重for循环的naive算法。

for m = 1 to n; do

  for x = 1 to n; do

    for y = 1 to n; do

      if weight(x, m) + weight(m, y) < weight(x, y); then

        weight(x, y) = weight(x, m) + weight(m, y);


你可能感兴趣的:(dijkstra)