近段时间,在看图论算法时,觉得挺有意思,所以觉得有必要总结一下:
概括:
1.最小生成树
2.单源最短路径
1.最小生成树
这个问题其实就是在找最小的连通所有点的路径权值和,典型的方法有kruskal,prim,复杂度分别为O(ElogE),O(E+VlogV)。
kruskal是这样的:
首先按边权值排序所有边,然后取出最小的,并判断是否有环,没有则加入到选择集合中,这其中涉及到的操作有:makeset,sort,find,unionset;
优化的关键在于排序(因为若使用并查集实现makeset,find,unionset效率是很高的),那么回想我们的sort不难看出线性的排序是很不错的,那么线性的排序有哪些呢?基数排序,计数排序,桶排序!其实用哪个都是可以的,但要根据具体的条件而定。
prim算法是这样的:
首先选择一个顶点,然后维护一个最优队列,选一个最优值,然后根据该定点,更新其它值,这其中操作有,extractmin,decrease。(小和松)
优化的关键在于这两个操作的复杂度,使用菲薄那切堆的话可以达到上述的复杂度,但是在一些数据结构中,可能会有更好的复杂度,比如,van Emdes等,例如如果权值是整数的话,我们可以使用类似于计数排序的方式实现最优队列,让权值等于数组的下标,让数组的元素等于顶点编号,然后相同权值的顶点连接成双链表。这样extractmin为O(1),decrease也是O(1)。所以复杂度可以到达O(E)。
2.单源最短路径
典型方法是bellman-ford,dijkstra。
bellman-ford是这样的:
首先选一个顶点,然后根据边更新每个连接的顶点,根据新更新的点再更新一次,一共更新顶点数次,最后检验负权回路
dijkstra是这样的:
首先选一个点,然后更新他链接的点,然后选一个最小的路径,把这点加到集合中,然后再以这个点为原点,在更新,操作有,extractmin,decrease。(小和松和prim几乎一样)
优化的关键和prim是非常像的,也是找一个关于操作复杂度最低的数据结构~但是实现上这个会复杂一点,可以用循环数组!