图论知识整理(2) 拓扑排序、最短路、最小生成树

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

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

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

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

定义:对一个有向无环图(Directed Acyclic Graph,简称DAG)进行拓扑排序,将图中所有顶点排成一个线性序列,使得图中任意一对顶点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连出的每一条边 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,若 ∈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连出的每一条边 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

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

转载于:https://www.cnblogs.com/TonyNeal/p/graph2.html

你可能感兴趣的:(数据结构与算法)