45
图图 图图 () 图图图

图论(二)

Embed Size (px)

DESCRIPTION

图论(二). 李子星. 内容提要. 最短路径问题 单源最短路径问题 Dijkstra 算法 Bellman-Ford 算法 SPFA 算法 任意点对最短路径问题 Floyd 算法 最小生成树问题 无向图的最小生成树问题 Prim 算法 Kruskal 算法 有向图的最小生成树问题. 单源最短路径问题. 给定一个有 n 个点的带权有向图,问从指定的起点开始,到其他所有点的最短路径。. 单源最短路径问题. 2. 2. 3. 8. 1. 1. 3. 10. 1. 4. 3. 5. 4. 4. 1. 6. 5. 3. - PowerPoint PPT Presentation

Citation preview

Page 1: 图论(二)

图论(二)

李子星

Page 2: 图论(二)

内容提要• 最短路径问题

– 单源最短路径问题• Dijkstra算法• Bellman-Ford算法• SPFA算法

– 任意点对最短路径问题• Floyd算法

• 最小生成树问题– 无向图的最小生成树问题

• Prim算法• Kruskal算法

– 有向图的最小生成树问题

Page 3: 图论(二)

单源最短路径问题

给定一个有 n个点的带权有向图,问从指定的起点开始,到其他所有点的最短路径。

Page 4: 图论(二)

单源最短路径问题

1

2

6 5

3

4

1

2

8

4

5

3

3

1

1

103

4

Page 5: 图论(二)

单源最短路径问题• 带权图中一个点到另一个点的最短路径一定唯一存在?–有路径通达且没有“负权回路”则一定存在–不一定唯一

• 单源最短路径是否一定能构成一棵树?–如果源点到其他所有点的最短路径都存在,则一定能找到一棵以指定的起点为根的树(边的方向总是从父亲指向儿子)

Page 6: 图论(二)

单源最短路径问题

1

2

6 5

3

4

1

2

8

4

5

-3

3

1

1

103

4

Page 7: 图论(二)

Dijkstra算法

如果边权没有负值,可以用 Dijkstra算法求解单源最短路径问题。

Page 8: 图论(二)

Dijkstra算法算法流程:1. 初始化所有点的 dist值为 +∞,起点的 di

st值为 0

2. 从所有点中找到未被标记的 dist值最小的点 x,将 x点标记

3. 检查所有 x引出的边,用 x点的 dist值与这条边的权值之和更新这条边指向的点的dist值(这个过程又被称为“松弛操作”)

4. 重复步骤 2和 3直到所有点都被标记

Page 9: 图论(二)

Dijkstra算法• 一个点的 dist值就是“已知的从起点到达它的最短路径长度”

• 如果记下每个点的 dist值最后一次更新是由哪条边的松弛操作完成的,这条边就是“已知的从起点到达它的最短路径的最后一条边”

• 一个点被标记也就意味着“这个点的 dist值已经不可能再被更新”,即“起点到它的最短路径已经求得”

Page 10: 图论(二)

Dijkstra算法

1

2

6 5

3

4

1

2

8

4

5

3

3

1

1

103

4

dist:0

dist:+∞

dist:+∞ dist:+∞

dist:+∞

dist:+∞

dist:1

dist:10

dist:3

dist:3

dist:5dist:2

dist:9

Page 11: 图论(二)

Dijkstra算法朴素的 Dijkstra算法的时间复杂度为 O(n^2)。

如果所有点的 dist值用一个堆来维护,“更新某个点的 dist值”和“寻找 dist值最小的点”就可以在 O(logn)的时间复杂度内完成。总时间复杂度就变成了 O(elogn),其中 e为图中的边数

实际上 Dijkstra算法就是 h函数为 0的 A*算法

Page 12: 图论(二)

Bellman-Ford算法

如果边权可以为负值,那么可以使用 Bellman-Ford算法求解单源最短路径问题。

Page 13: 图论(二)

Bellman-Ford算法算法流程:1. 初始化所有点的 dist值为 +∞,起点的 dist值为

0

2. 检查所有边 uv,用 u点的 dist值与这条边的权值之和更新 v点的 dist值。即对所有的边执行一次松弛操作。若此步骤中某个点的 dist值更新了,那么可以说此步骤是“有收获的”

3. 直到上一轮步骤 2没有收获,或步骤 2已经重复了 n轮,否则再重复一次步骤 2。若最后一轮步骤 2仍旧是有收获的,那么说明起点能够到达一个负权回路,否则目标就已经达成了。

Page 14: 图论(二)

Bellman-Ford算法证明:• 如果起点能够到达某个负权回路,那么显然,步骤 2总是会有收获。

• 如果起点无法到达一个负权回路,那么当所有点的 dist值到达最低值时,步骤 2就不再有收获了。

• 而一条最短路径一定没有环,即一条最短路径经过的边数一定不会超过 n-1(经过了所有其他的点),所以 n-1轮后,任何一个点作为终点的最短路径一定已经求得。

Page 15: 图论(二)

Bellman-Ford算法

时间复杂度显然是 O(ne)

Page 16: 图论(二)

SPFA算法

稍微改进一下 Bellman-Ford算法的过程,就得到 SPFA( Shortest Path Faster Algorithm)算法。

Page 17: 图论(二)

SPFA算法算法流程:1. 初始化所有点的 dist值为 +∞,起点的 di

st值为 0 “,将起点加入一个 待检查点”的队列 q

2. 从队列 q的队首中取出一个节点 x,对 x引出的所有边执行松弛操作,若某个点的dist值被更新了且这个点不在队列 q中,则将其加入队尾

3. 重复步骤 2直到某个点入队超过 n次或队列为空

Page 18: 图论(二)

SPFA算法

有理论能够证明, SPFA算法的平均时间复杂度为 O(e) 。但是有可能退化,最坏会到 O(en)。

比较适合于稀疏图中求解单源最短路径。

如果不用队列,改用栈可以么?

Page 19: 图论(二)

单源最短路径问题

算法 时间复杂度

Dijkstra O(n^2),或者用堆优化到 O(elogn)

Bellman-Ford O(en)

SPFAO(e),只是平均情况,最坏可能退化到 O(en),但一般来说效果很好

Page 20: 图论(二)

任意点对最短路径问题

给定一个有 n个点的带权有向图,问任意两个点之间的最短路径长度。

Page 21: 图论(二)

Floyd算法代码如下( w最初是图的邻接矩阵,算法结束后是任意点对间的最短路径长度):

for k=1 to n do

for i=1 to n do

for j=1 to n do

if (w[i,k]+w[k,j]<w[i,j])

w[i,j]=w[i,k]+w[k,j]

Page 22: 图论(二)

Floyd算法for k=1 to n do

// 此时的 w[x,y]为: x到 y的“中途只能// 经过 1..k-1这些点的”最短路径长度// 下面的二重循环则是求“中途只能// 经过 1..k这些点的”最短路径长度for i=1 to n do

for j=1 to n do if (w[i,k]+w[k,j]<w[i,j])

w[i,j]=w[i,k]+w[k,j]

在 w[i,j]被更新时记下其因哪个 k被更新,将之存储在mid[i,j]中,则mid[i,j]就是 i到 j的最短路径中经过的编号最大的点,由此可以还原出任意点对间的具体的最短路径。

Page 23: 图论(二)

Floyd算法

k

x y只经过 1..k-1

只经过

1..k-1

只经过1..k-1

Page 24: 图论(二)

Floyd算法如果有负权边但没有负权回路, Floyd算法还是正确的么?

答案是依然正确。但是 Floyd算法没法判断图中是否有负权回路存在。

时间复杂度显然是 O(n^3)的。

Page 25: 图论(二)

Floyd算法

如果图中有负权回路存在, Floyd算法最后得到的会是什么?

如果要求图(可能是无向图)的最小环, Floyd算法可以给你什么启示么?

Page 26: 图论(二)

最短路径问题

如果要求次短路径,甚至第 k短路径呢?

如果这个图存在负权回路,但要求每个点不走两次的最短路径呢?

Page 27: 图论(二)

无向图的最小生成树问题给定一个连通的带正权无向图,求此图的一个边集,要求:( 1)将不在此边集的边全删除后,图依然连通;( 2)边集中的边的权值之和最小。

易知这个边集一定构成一棵树,因此它又被称为“最小生成树”

Page 28: 图论(二)

无向图的最小生成树问题

1

2

5 4

3

2 3

1 4

2

3

4

17

3

Page 29: 图论(二)

无向图的最小生成树问题

• 将原图点集分成两个不相交的集合 A和 B

• 原图中所有连接了 A和 B的边中权值最小的那条,一定可以作为最小生成树中的一条边

Page 30: 图论(二)

无向图的最小生成树问题

1

2

5 4

3

2 3

1 4

2

3

4

17

3

Page 31: 图论(二)

Prim算法算法流程:1. 任选一个点 s得到集合 A={s},初始化 di

st[i]为 w[s,i], link[i]=s

2. 在 V-A中选取 dist最小的点 x,将 x加入集合 A,检查所有 V-A中的点 i,若 w[x,i]<dist[i]则 dist[i]=w[x,i]且令 link[i]=x

3. 重复步骤 2直到 A=V,此时所有 V-{s}中的点 i与 link[i] 相连的边就构成了原图的一个最小生成树,此外 dist[i]就是连接了 i与 link[i]的边的权值

Page 32: 图论(二)

Prim算法

1

2

5 4

3

2 3

1 4

2

3

4

17

3

Page 33: 图论(二)

Prim算法

时间复杂度是为O(n^2)的。

正确性依赖于之前说的原理。

虽然最小生成树本身是“无根树”,但 link数组实际上对应了一棵以 s为根的“有根树”,对于每个节点 i, link[i]就是其在这棵树中的父节点。

Page 34: 图论(二)

Kruskal算法算法流程:1. 将所有的边按权值从小到大排序,初始化

A[i]={i}对所有的 i, A[1..n]构成原图点集的一个划分

2. 依边权从小到大依次检查每条边,若这条边连接的两个点不在一个划分块中,则标记这条边,然后将这两个划分块合并

3. 重复步骤 2,直到所有点都在一个划分块中为止。最后所有标记的边构成原图的一个最小生成树

Page 35: 图论(二)

Kruskal算法

1

2

5 4

3

2 3

1 4

2

3

4

17

3

Page 36: 图论(二)

Kruskal算法

原图点集的划分通常使用并查集来维护,所以 Kruskal算法的时间复杂度就是 O(eloge)。

显然,如果图是稀疏图, Kruskal算法效率应该好于 Prim算法,而对于稠密图则相反。

Page 37: 图论(二)

无向图的最小生成树问题

如果图是动态变化的呢?比如图中的边会不断增加,或者不断减少。

如果要求的不是最小生成树,而是次小生成树,甚至第 k小生成树呢?

如果每条边有两个参数 c和 w,要求选出的边集的 c之和与 w之和的比值最小呢?这个又被称为“最优比率生成树”

Page 38: 图论(二)

有向图的最小生成树问题给定一个连通的带正权有向图,并指定其中的某个点 s,求此图的一个边集,要求:( 1)将不在此边集的边全删除后, s到其他所有点都有路径。( 2)边集中的边的权值之和最小。显然这个边集一定构成一棵以 s为根的有根树,且这棵树中的边都是父节点指向儿子节点的。这样的边集又被称为原图以 s为根的“最小树形图”。

Page 39: 图论(二)

有向图的最小生成树问题

1

2 4

3 5

35

5

4

2 6

3

7

Page 40: 图论(二)

有向图的最小生成树问题算法流程:1.对 s 外的每个点 i,找到指向 i的边中权值最小的那条,将这些边放入边集 A0

2.若图中没有环且没有收缩点,则 A0即为所求,算法结束;若有环则进入步骤 3 ;若没有环但有收缩点,则进入步骤 4

3.将每个环收缩为一个点,同时将这个环中的边从A0 剔除,然后回到步骤 1。收缩的具体操作如下:1. 假设收缩产生的新点为 P2.对于任意环外点 x指向环内点 y的权值为 w的边 xy,生成一条边 xP,并且权值改为 w 减去环中指向 y的边的权值,这条边实际上是原本的 xy的“等价边”

Page 41: 图论(二)

有向图的最小生成树问题

S

9 5

39 4

3738 5

9

48

46

S

9-7 5-33

9-48-3

9-5

4-36

4 8-5

收缩

Page 42: 图论(二)

有向图的最小生成树问题4. 此时的 A0(没环)对于现在的图(有收缩点)来说,就是一棵以 s为根的最小生成树了,但由于存在收缩点,所以现在的图还不是原图,所以需要把收缩点展开,以还原到原图。展开后可能依然存在收缩点,需要重复此步骤直到没有收缩点为止,那时的 A0即为所求1. 展开时需要将其在收缩时从 A0中剔除的边加回到 A0

2. 对每个展开后的收缩点,其中肯定有一个点有两条边指向它,其中一条是所在收缩点外的某点指向它的,另一条则是收缩点内的某点指向它的,将后者从 A0 剔除

Page 43: 图论(二)

有向图的最小生成树问题

S

9-7 5-33

9-48-3

9-5

4-36

48-5

S

9 5

39 4

3738 5

9

48

46

展开

Page 44: 图论(二)

有向图的最小生成树问题这个过程简而言之就是:• 找最小边• 收缩• 找最小边• 收缩• ……

• 展开• 展开• ……

Page 45: 图论(二)

练习题• POJ1502

• POJ3637

• POJ1511

• POJ1062

• POJ1860

• POJ1797

• POJ2253

• POJ1125

• POJ1258

• POJ2485

• POJ2075

• POJ3625

• POJ1679

• POJ3164