zoukankan      html  css  js  c++  java
  • 图论知识整理(2) 拓扑排序、最短路、最小生成树

    =====================================

    发现以前图论学的很不好,什么都不会,现在开始整理图论知识了

    作者就是个蒟蒻,ORZ各位大神们

    =====================================

    定义:对一个有向无环图(Directed Acyclic Graph,简称DAG)进行拓扑排序,将图中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则u在线性序列中出现在v之前。

    说的好像很有道理,然而我并没有看懂它在讲什么。。

    就比如说现在有一份工作,这份工作有5个部分,分别为v1,v2,v3,v4,v5

    好了,那么要做v2首先得做v1、v3;要做v1首先得做v4、v5

    那么一个拓扑排序的序列就是v4、v5、v1、v3、v2

    其实就表示制约与被制约的关系(不知道描述的清不清楚)

    有向图存在环就不鞥呢进行拓扑排序。

    拓扑排序算法:

      每次挑选入度为0的顶点输出(不计次序,所以答案不唯一)。

      如果最后发现输出的顶点数小于n(或者写成|V|),则表明有回路存在。

      初始化:top=0 (栈顶指针);

      将初始状态所有入度为0的顶点压栈;

      i=0 (计数器);

      While top>0 (栈非空) do

        顶点v(栈顶元素)出栈并输出;

        计数器i增加1;

        For 与v邻接的顶点u do //用邻接表,每条边被访问1次,所以总的复杂度是O(|E|);而用邻接矩阵,则每次需要O(n)的复杂度;

          dec(indgr[u]);

          If indgr[u]=0 then 顶点u入栈;

      if i<|V| then exit(有回路信息)。

      最短路问题:

    在带权图G =(V,E)中,若顶点 Vi,Vj是图G的两个顶点,从顶点Vi到Vj的路径长度定义为路径上各条边的权值之和。 从顶点Vi到Vj可能有多条路径,其中路径长度最小的一条路径称为顶点Vi到Vj的最短路径。 对于不带权的图,只要认为每条边权值是1,即可当作带权图一样处理了。

    单源最短路径SSSP(Single-Source Shortest Path) 从某个顶点(源点)到其它顶点(终点)的最短路径

      常用算法:

      Dijkstra  

      Bellman-Ford(升级为SPFA)

    多源最短路径APSP(All Pairs Shortest Paths) 求图中每一对顶点间的最短路径。

      常用算法:

      Floyd

    1. SPFA

    每次取出队首结点u,并且用u点当前的最短路径估计值对边(u,v)进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点加入队列。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。

    判断有无负环:如果某个点进入队列的次数超过N/2次,则存在负环。平均来说O(kE),k为较小的常数。

    但是可以被网格图和负权环卡到O(VE)

    ——wyh聚聚

    2. Dijkstra

    初始化: dis[v]=w[s,v];

    其中,w[s,v]=maxint表示s到v无直接边

    dis[s]=0; S={s}; //S表示已经拓展的点集

    For i:=1 to n-1 do 从V-S中取出一个顶点u进行拓展,

      要求:dis[u]=min{dis[v]|v∈V-S} //此处也是算法的关键,s到u的最短路径d[u]已经不可能再小了。此处可以用堆优化。

      S=S+{u}

      For u连出的每一条边<u,v> do

        Relax(u,v)

    不加堆优化O(V^2) 建议稠密图使用

    加堆优化O(ElogE) 建议稀疏图使用

    3. Floyd:这个实在太简单了,就不讲了,利用动态规划的思想,复杂度O(V^3),但是可以求所有点对之间的最短路径。

    但是一般来说没有必要求那么多。

    要求的话,一种用Floyd,O(V^3),一种用SPFA或Dijkstra,乘上V,SPFA O(kVE) Dijkstra O(V^3), 堆优化O(VElogE)

    (= =)貌似也讲太多了。。

    最小生成树

    一个连通图的生成树是一个极小连通子图,它含有图中全部顶点,但只有足以构成一棵树的n-1条边。 对于连通的带权图G,其生成树也是带权的。 生成树上各边权值的总和,称为该树的权。 权值最小的生成树,称为G的最小生成树(MST,Minimum Spanning Tree)。 解决最小生成树问题一般有两种算法Prim和Kruskal。

    1. PRIM

    Prim算法基于一种贪心策略: 每次选取离当前点集最近的点加入MST。 多用于稠密图。 初始时,MST是只包含一个点的集合,由于每个点最终都要被包含在MST内,所以Prim算法可以由图中的任意一点开始。与dji

    ---恢复内容结束---

    =====================================

    发现以前图论学的很不好,什么都不会,现在开始整理图论知识了

    作者就是个蒟蒻,ORZ各位大神们

    =====================================

    定义:对一个有向无环图(Directed Acyclic Graph,简称DAG)进行拓扑排序,将图中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则u在线性序列中出现在v之前。

    说的好像很有道理,然而我并没有看懂它在讲什么。。

    就比如说现在有一份工作,这份工作有5个部分,分别为v1,v2,v3,v4,v5

    好了,那么要做v2首先得做v1、v3;要做v1首先得做v4、v5

    那么一个拓扑排序的序列就是v4、v5、v1、v3、v2

    其实就表示制约与被制约的关系(不知道描述的清不清楚)

    有向图存在环就不鞥呢进行拓扑排序。

    拓扑排序算法:

      每次挑选入度为0的顶点输出(不计次序,所以答案不唯一)。

      如果最后发现输出的顶点数小于n(或者写成|V|),则表明有回路存在。

      初始化:top=0 (栈顶指针);

      将初始状态所有入度为0的顶点压栈;

      i=0 (计数器);

      While top>0 (栈非空) do

        顶点v(栈顶元素)出栈并输出;

        计数器i增加1;

        For 与v邻接的顶点u do //用邻接表,每条边被访问1次,所以总的复杂度是O(|E|);而用邻接矩阵,则每次需要O(n)的复杂度;

          dec(indgr[u]);

          If indgr[u]=0 then 顶点u入栈;

      if i<|V| then exit(有回路信息)。

      最短路问题:

    在带权图G =(V,E)中,若顶点 Vi,Vj是图G的两个顶点,从顶点Vi到Vj的路径长度定义为路径上各条边的权值之和。 从顶点Vi到Vj可能有多条路径,其中路径长度最小的一条路径称为顶点Vi到Vj的最短路径。 对于不带权的图,只要认为每条边权值是1,即可当作带权图一样处理了。

    单源最短路径SSSP(Single-Source Shortest Path) 从某个顶点(源点)到其它顶点(终点)的最短路径

      常用算法:

      Dijkstra  

      Bellman-Ford(升级为SPFA)

    多源最短路径APSP(All Pairs Shortest Paths) 求图中每一对顶点间的最短路径。

      常用算法:

      Floyd

    1. SPFA

    每次取出队首结点u,并且用u点当前的最短路径估计值对边(u,v)进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点加入队列。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。

    判断有无负环:如果某个点进入队列的次数超过N/2次,则存在负环。平均来说O(kE),k为较小的常数。

    但是可以被网格图和负权环卡到O(VE)

    ——wyh聚聚

    2. Dijkstra

    初始化: dis[v]=w[s,v];

    其中,w[s,v]=maxint表示s到v无直接边

    dis[s]=0; S={s}; //S表示已经拓展的点集

    For i:=1 to n-1 do 从V-S中取出一个顶点u进行拓展,

      要求:dis[u]=min{dis[v]|v∈V-S} //此处也是算法的关键,s到u的最短路径d[u]已经不可能再小了。此处可以用堆优化。

      S=S+{u}

      For u连出的每一条边<u,v> do

        Relax(u,v)

    不加堆优化O(V^2) 建议稠密图使用

    加堆优化O(ElogE) 建议稀疏图使用

    3. Floyd:这个实在太简单了,就不讲了,利用动态规划的思想,复杂度O(V^3),但是可以求所有点对之间的最短路径。

    但是一般来说没有必要求那么多。

    要求的话,一种用Floyd,O(V^3),一种用SPFA或Dijkstra,乘上V,SPFA O(kVE) Dijkstra O(V^3), 堆优化O(VElogE)

    (= =)貌似也讲太多了。。

    最小生成树

    一个连通图的生成树是一个极小连通子图,它含有图中全部顶点,但只有足以构成一棵树的n-1条边。 对于连通的带权图G,其生成树也是带权的。 生成树上各边权值的总和,称为该树的权。 权值最小的生成树,称为G的最小生成树(MST,Minimum Spanning Tree)。 解决最小生成树问题一般有两种算法Prim和Kruskal。

    1. PRIM

    Prim算法基于一种贪心策略: 每次选取离当前点集最近的点加入MST。 多用于稠密图。 初始时,MST是只包含一个点的集合,由于每个点最终都要被包含在MST内,所以Prim算法可以由图中的任意一点开始。与djikstra很相似,具体在后面会详细更新。

    2. KRUSKAL

    同样,在以后的文章中也会详细介绍,敬请期待。。

    这篇文章由TonyFang发布。 所有解释权归TonyFang所有。 Mailto: tony-fang@map-le.net
  • 相关阅读:
    eclips git中的add to Index无效解决
    关于Promise 简单使用理解
    小程序顶部可滚动导航
    读jQuery源码
    Web UI
    JavaScript滚动条插件源码
    Ajax异步刷新地址栏url改变(利用Html5 history.pushState实现)
    angular2如何按需加载?
    如何把bootstrap用webpack打包
    typings的理解
  • 原文地址:https://www.cnblogs.com/TonyNeal/p/graph2.html
Copyright © 2011-2022 走看看