Graph Search and Connectivity


Generic Graph Search

Goals 1. find everything findable

2. don't explore anything twice

Generic Algorithm (given graph G, vertex S)

--- initialize S explored (all others unexplored)

--- while possible:

--- choose an edge(u, v) with u explored and v unexplored

--- mark v explored

     1. Breadth-First Search (BFS)     O(m+n) time using a queue

--- explore nodes in 'layers'

--- can compute shortest paths

--- can compute connected components of an undirected graph

The basics:pseudocode

        BFS(Graph G, start vertex s)

(all nodes initially unexplored)

mark s as explored

let Q = queue data structure(FIFO), initialized with s

while Q != 0:

remove the first node of Q, call it v

for each edge(v, w):

if w unexplored

mark w as explored

add into Q (at the end)

          Shortest Paths:

Goal: compute dist(v), the fewest # of edges on a path from s to v

Extra code:

initialize dist(v) = 0 if v == s

when considering edge(v, w):

if w unexplored then set dist(w) = dist(v) + 1

claim: at termination, dist(v) = i  <=>  v in ith layer

          Undirected Connectivity

let G = (V, E) be an undirected graph

Connected components == the 'pieces' of G

Goal: compute all connected components(why? check if network is disconnected, graph visualization, clustering, similarity)

all nodes unexplored

(assume labelled 1 to n)

for i = 1 to n

if i not yet explored

BFS(G, i)      //discovers precisely i's connected components

    2. Depth-First Search (DFS)       O(m+n) time using a stack

--- explore aggressively like a maze, backtrack only when necessary

--- compute topological ordering of directed acycle graph(DAG)

--- compute connected components in directed graphs

pseudocode:

use a stack instead of a queue

recursive version:

DFS(Graph G, start vertex s)

mark s as explored

for every edge(s,v)

if v unexplored

DFS(G,v)

        Application: Topological Sort   (DAG)

Definition: A topological ordering of a directed graph G is a labelling f of G's node's such that:

1. the f(v)'s are the set{1,2,...,n}

2. (u,v)  => f(u) < f(v)

note that if G has directed cycle => no topological ordering

        Straightforward solution to Topological Sort

note: every directed acyclic graph has a sink vertex(入度为0的node,无前驱)

To compute topological ordering:

let v be a sink vertex of G

set f(v) = n

recurse on G - {v}

(1) 从有向图中选一个没有前驱的顶点

(2) 从图中删去该点,并删去从该点出发的所有边

(3) 重复上两步,直到图中再没有有前驱的点为止

        Topological Sort via DFS

        DFS(G, s)

mark s explored

for every edge(s, v)

if v not yet explored

DFS(G, v)

set f(s) = current_label

current_label --

DFS-loop(Graph G)

mark all node unexplored

current_label = n

for each vertex v:

if v unexplored

DFS(G, v)

          3. Computing Strong Components: The Algorithm

Strongly connected Components

Formal Definition: the strongly connected Components(SCCs) of a directed graph G are the equivalance classes of the relation:

u~v <=> u ->v and v -> u in G

Kosaraju's Two-Pass Algorithm   2*DFS = O(m+n)

1. let Gr = G with all arcs reversed

2. run DFS-loop on Gr       <---------- Goal: compute 'magical ordering' of nodes

let f(v) = 'finishing time' of each v

3. run DFS-loop on G        <---------- Goal: discover the SCCs one-by-one

processing nodes in decreasing order of finishing times

SCCs = nodes with the same 'leader'

pseudocode:

DFS(G, i)

make i as explored

set leader(i) = node s

for each arc(i, j):

if j not yet explored:

DFS(G, j)

t++

set f(i) = t      // i's finishing time

DFS-loop(Graph G)

global variable t = 0    // # of nodes pressed so far (for finishing times in 1st pass)

global variable s = Null  // current source vertex  (for leaders in 2nd pass)

Assume nodes labelled 1 to n

for i = n down to 1

if i not yet explored

s = i

DFS(G, i)

Python Code:

import sys
import threading
import copy threading.stack_size(67108864)
sys.setrecursionlimit(300000) def DFS(edges, i, index):
global t, vertices, new_vertices, s, compare
if index == 1: # 1st pass
vertices[i-1][1] = True # mark it explored
if index == 2: # 2nd pass
vertices[compare[i]-1][1] = True
vertices[compare[i]-1].append(s) # set leader(i) = node s
if i in edges:
for v in edges[i]:
if index == 1:
if vertices[v-1][1] == False:
DFS(edges, vertices[v-1][0], index)
if index == 2:
if vertices[compare[v]-1][1] == False:
DFS(edges, vertices[compare[v]-1][0], index) if index == 1:
t = t + 1 # i's finishing time
vertices[i-1].append(t)
temp = vertices[i-1].copy()
temp[1] = False
new_vertices.append(temp)
compare[vertices[i-1][0]] = t def DFS_loop(edges, index):
global t, vertices, new_vertices, s
t = 0 #for finishing times in 1st pass
n = len(vertices)
for i in range(1, n+1):
v = vertices[n-i]
if v[1] == False:
s = v[0]
DFS(edges, v[0], index) def main():
global vertices, new_vertices, compare
f = open('SCC.txt')
_f = list(f)
vertices = list() #[number, False] false indicates unexplored
new_vertices = list() #[number, False, t, s]
edges = dict() # {1:[2,5,6...]...}
edges_rev = dict() # {2:[8,9,5...]...}
compare = dict()
for i in range(0, 875714): #875714 initialize V
vertices.append([i+1, False])
for edge in _f: # initialize E
temp = edge.split()
edge_temp = [int(temp[0]), int(temp[1])]
edge_rev_temp = [edge_temp[1], edge_temp[0]]
if edge_temp[0] not in edges:
edges[edge_temp[0]] = [edge_temp[1]]
else:
edges[edge_temp[0]].append(edge_temp[1])
if edge_rev_temp[0] not in edges_rev:
edges_rev[edge_rev_temp[0]] = [edge_rev_temp[1]]
else:
edges_rev[edge_rev_temp[0]].append(edge_rev_temp[1]) DFS_loop(edges_rev, 1)
vertices = copy.deepcopy(new_vertices)
DFS_loop(edges, 2) result = dict()
for item in vertices: # nodes with the same 'leader'
if item[3] not in result:
result[item[3]] = 1
else:
result[item[3]] = result[item[3]] + 1 r = list() #output the sizes of the 10 largest SCCs
for key in result:
r.append(result[key])
r = sorted(r, reverse = True)
print(r[0:9]) if __name__ == '__main__':
thread = threading.Thread(target = main)
thread. start()

【Python排序搜索基本算法】之深度优先搜索、广度优先搜索、拓扑排序、强联通&Kosaraju算法的更多相关文章

  1. python 实现图的深度优先和广度优先搜索

    在介绍 python 实现图的深度优先和广度优先搜索前,我们先来了解下什么是"图". 1 一些定义 顶点 顶点(也称为"节点")是图的基本部分.它可以有一个名称 ...

  2. C语言数据结构与算法之深度、广度优先搜索

    一.深度优先搜索(Depth-First-Search 简称:DFS) 1.1 遍历过程: (1)从图中某个顶点v出发,访问v. (2)找出刚才第一个被顶点访问的邻接点.访问该顶点.以这个顶点为新的顶 ...

  3. 算法与数据结构基础 - 广度优先搜索(BFS)

    BFS基础 广度优先搜索(Breadth First Search)用于按离始节点距离.由近到远渐次访问图的节点,可视化BFS 通常使用队列(queue)结构模拟BFS过程,关于queue见:算法与数 ...

  4. 基于visual Studio2013解决算法导论之046广度优先搜索

     题目 广度优先搜索 解决代码及点评 // 图的邻接表表示.cpp : 定义控制台应用程序的入口点. // #include <iostream> #include <stac ...

  5. 算法学习记录-图——应用之拓扑排序(Topological Sort)

    这一篇写有向无环图及其它的应用: 清楚概念: 有向无环图(DAG):一个无环的有向图.通俗的讲就是从一个点沿着有向边出发,无论怎么遍历都不会回到出发点上. 有向无环图是描述一项工程或者系统的进行过程的 ...

  6. 有向图的强联通tarjan算法(判断是否为强联通模板)(hdu1269)

    hdu1269 迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tot ...

  7. 算法数据结构 | 三个步骤完成强连通分量分解的Kosaraju算法

    强连通分量分解的Kosaraju算法 今天是算法数据结构专题的第35篇文章,我们来聊聊图论当中的强连通分量分解的Tarjan算法. Kosaraju算法一看这个名字很奇怪就可以猜到它也是一个根据人名起 ...

  8. POJ 3180-The Cow Prom (图论-有向图强联通tarjan算法)

    题目大意:有n个牛在一块, m条单项绳子, 有m个链接关系, 问有多少个团体内部任意两头牛可以相互可达 解题思路:有向图强连通分量模版图 代码如下: #include<stdio.h> # ...

  9. 深度优先搜索(DFS)与广度优先搜索(BFS)的Java实现

    1.基础部分 在图中实现最基本的操作之一就是搜索从一个指定顶点可以到达哪些顶点,比如从武汉出发的高铁可以到达哪些城市,一些城市可以直达,一些城市不能直达.现在有一份全国高铁模拟图,要从某个城市(顶点) ...

随机推荐

  1. Java中XML格式的字符串4读取方式的简单比较

    Java中XML格式的字符串4读取方式的简单比较 1.java自带的DOM解析. import java.io.StringReader; import javax.xml.parsers.Docum ...

  2. 常用UML模型简要小结

    关系: 关联(组合,生命周期相同:聚合,物以类聚),依赖,泛化(继承),实现 还有 包含,细化复用已有用例:扩展,非必要主要的用例 图: 1.用例图:就是描述一个功能场景(集合),其实用例编写(前后置 ...

  3. StyleCop源码分析

    前言: 由于最近在进行项目配置,配置内容:根据一个结构体,一一对应地配置xml文件(两个) 写一个和此结构体对应的类(只包含属性,字段).反复配置后,觉得太繁琐,因此想到使用程序完成自动配置,网上搜索 ...

  4. maven 创建Hadoop程序

    这里用来将新建的maven project 放入到现有的maven working set 中,这样我们就能看到项目之间的层级关系 选择下面的程序 在父项目中创建公共的pom,在pom中维护项目所需要 ...

  5. oracle学习

    在平时的工作学习中,经常需要使用到oracle数据库,将平时用到的一些技巧记录在这里,以便以后随时可以翻阅. 1.日期类型的比较 插入日期时,经常会使用sysdate来插入数据,但sysdate插入的 ...

  6. Mac上Homebrew的使用 (Homebrew 使 OS X 更完整)

    0 Homebrew是啥? “Homebrew installs the stuff you need that Apple didn’t.——Homebrew 使 OS X 更完整”. Homebr ...

  7. 6.6 Android 编译机制的变迁

    我们使用Java开发android,在编译打包APK文件时,会经过以下流程 Java编译器将应用中所有Java文件编译为class文件(JVM运行的是.class文件,而DVM是.dex文件) dx工 ...

  8. ES6 fetch函数与后台交互

    最近在学习react-native,遇到调用后端接口的问题.看了看官方文档,推荐使用es6的fetch来与后端进行交互,在网上找了一些资料.在这里整理,方便以后查询. 1.RN官方文档中,可使用XML ...

  9. Java入门 任务表

    Java IO Java ,MySQL Java Internet 线程,同步 冒泡法排序 1.

  10. [Xamarin] 簡單使用AlertDialog (转帖)

    這東西跟Toast 很像,有方便提示的作用 像是Windows 上面的MessageBox 或是 Javascript 的 Alert 會先阻斷使用者並且下一個決定 很簡單我就不贅述,基本上透過 Al ...