图论知识整理(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
同样,在以后的文章中也会详细介绍,敬请期待。。