现在的位置: 首页 > 综合 > 正文

算法设计与分析课程Part1笔记(4)

2014年10月12日 ⁄ 综合 ⁄ 共 1849字 ⁄ 字号 评论关闭

4. 图搜索及其连通性

对于图来说,考虑的几个比较重要的因素就是连通性和路径;连通性关注的有强连通分量和特殊结构(例如web中的蝴蝶结构),路径关注的有两个节点间的最短路径和任意节点间的所有简单路径。

连通性和路径其实都是关于图中的搜索,通过图搜索希望能够找到目标节点,并且每个节点尽量访问一次(或者说复杂度是线性的)。

4.1 BFS和DFS

广度优先和深度优先是非常熟悉和基础的两个图搜索算法

其中BFS采用FIFO以层的方式对图中节点进行访问,能够计算两点间最短路径和发现无向图中的连通分量;而DFS是回溯探索,能够计算有向图中的拓扑序和有向图中的连通分量。

BFS(Graph G,Start vertex s):

     -- mark s as explored

    -- initial Q as a queue, and push s into Q

    -- while Q is not empty

        -- pop a node v from Q

        -- for each edge (v,w)

            -- if w unexplored

            -- mark w as explored

            -- push w into Q

BFS可以访问从特定节点s到任意节点v的所有路径。其算法复杂度为O(m+n).(如果是用邻接矩阵来表示图G,算法复杂度就不是O(m+n),最差为O(n2))

利用BFS进行连通分量的计算,对每个节点进行BFS,只要进行一次,就是完成了一次连通分量访问的切换。

利用BFS进行最短路径的计算:

 -- compute the shortest path from s to v, anddenote it as d(v)

 -- initial d(v), if v==s d(v)=0, and if v isnot s d(v)=oo

 -- initial Q as a queue, push s into Q

 --while Q is not empty

      -- pop a node w from Q

      -- for each edge (s,w)

      -- if w unexplored

           --mark w as explored

           --d(v)++

           -- if w==v break

     利用DFS可以计算拓扑排序和有向网络中的连通分量,其实现借助堆栈比较容易。

    DFS(Graph G, start vertex s)(Recursive Version):

      -- mark s as explored

     -- for every edge (s,v)(for every edge which is connected to s)

      -- if v unexplored

      -- DFS(G,v)

4.2 拓扑排序和强连通分量

    这两者都可以通过DFS来实现。

    拓扑排序的定义:有向图G的拓扑排序指的是对G中的节点进行标注,并满足1.标注的值是从1到n;2.如果有有向边(u,v),则u的标注值小于v的标注值。

可以从上面的定义知道,如果有向图G中存在循环,是无法进行拓扑排序的;拓扑排序的一个应用是在流程先后顺序上,例如课程顺序安排中的先修和后续等。

进行拓扑排序的方案1:Streight-ForwardSolution:

  -- letv be a sink vertex of G

  -- set f(v)=n

  -- recursive on G-v

注:对于任意有向无环图,至少存在一个sink节点,所谓sink节点就是有出无进,所有输血过多了sink了,通过拓扑排序的定义,sink节点应该是图中排序值最高的节点。

利用DFS进行拓扑排序。

DFS-loop(Graph G):

-- mark allnodes unexplored

--current_label=n (global invariant)

-- for eachvertex v in G:

    -- if v not explored

    -- DFS(G,v)

DFS(G,v):

-- mark vexplored

-- for everyedge (v,s):

     -- if s unexplored:

     -- DFS(G,s)

--set f(v)=current_label

--current_label --

用DFS进行拓扑排序的时间复杂度为O(n+m).

还可以利用DFS计算有向图中的SCC。这里主要讲述Kosaraju算法。可以在O(m+n)时间内计算SCC。

算法描述:

注:一个关于SCC的编程题,已经上传到我的微盘上,可以下载http://vdisk.weibo.com/s/9LWVl/1343806060

抱歉!评论已关闭.