GRAPH ALGORITHM
Graph A pair G = (V,E) – V = set of vertices (node) – E = set of edges (pairs of vertices) V = (1,2,3,4,5,6,7) E = ( (1,2),(2,3),(3,5),(1,4),(4,5),(6,7) )
Terms you should already know directed, undirected graph Weighted graph Bipartite graph Tree – Spanning tree Path, simple path Circuit, simple circuit Degree
Representing a Graph Adjacency Matrix – A = |V|x|V| matrix a xy = 1when there is an edge connecting node x and node y a xy = 0otherwise
Representing a Graph Adjacency List – Use a list instead of a matrix – For each vertex, we have a linked list of their neighbor
Representing a Graph Incidences Matrix Row represent edge Column represent node
DEPTH FIRST SEARCH
Connectivity Problem
Depth-First-Search void explore(G, v) // Input: G = (V,E) is a graph; v V // Output: visited[u] is set to true for all nodes u reachable from v { visited[v] = true previsit(v) for each edge (v,u) E if not visited[u] explore(G,u) postvisit(v) }
Example ABDE FI J CG H LK
explore(A) A BD EF I J C G H ABDE FI J CG H LK
Extend to Graph Traversal
Graph Traversal using DFS void traverse(G) { for all v V visited[v] = false for all v V if not visited[v] explore(G,v) }
Complexity Analysis Each node is visited once Each edge is visited twice – Why? O( |V| + |E|)
CONNECTED COMPONENT
Connectivity in Undirected Graph
Connected Component Problem Input: – A graph Output: – Marking in every vertices identify the connected component Let it be an array ccnum, indexed by vertices
Example {A,B,E,I,J} {C,D,G,H,K,L} {F} AB D EF I J C G H KL
Solution Define global variable cc In previsit(v) – ccnum[v] = cc Before calling each explore – cc++
DFS VISITING TIME
Ordering in Visit void previsit(v) pre[v] = clock++ void postvisit(v) post[v] = clock++
Example AB D EF I J C G H KL
AB D EF I J C G H KL [1,10] [4,9] [5,8] [6,7] [2,3] [23,24] [11,12][12,21] [14,17] [15,16] [18,19] [13,20]
Ordering in Visit The interval for node u is [pre(u),post(u)] The inverval for u,v is either Contained disjointed Never intersect
Type of Edge in Directed Graph A B CD forward cross back tree [Pre,Post] ordering of (u,v)Edge Type [u [v v] u]Tree/Forward [v [u u] v]Back [v v] [u u]Cross
Directed Acyclic Graph (DAG) A directed Graph without a cycle – Has “source” A node having only “out” edge – Has “sink” A node having only “in” edge How can we detect that a graph is a DAG – What should be the property of “source” and “sink” ?
Solution A directed graph is acyclic if and only if it has no back edge Sink – Having lowest post number Source – Having highest post number
TOPOLOGICAL SORTING
Linearization of Graph
Linearization One possible linearization B,A,D,C,E,F Order of work that can be done w/o violating the causality constraints A BD E F C
Topological Sorting Problem
Topological Sorting Do DFS List node by post number (descending) [1,12] [2,9] [3,8] [4,5] [6,7] [10,11] A BD E F C
BREADTH FIRST SEARCH
Distance of nodes The distance between two nodes is the length of the shortest path between them S A 1 S C 1 S B 2 E DC A B S S starting
DFS and Length DFS finds all nodes reachable from the starting node – But it might not be “visited” according to the distance E D C A B S S
Ball and Strings We can compute distance by proceeding from “layer” to “layer” EDCA B S S
Shortest Path Problem (Undi, Unit) Input: – A graph, undirected – A starting node S Output: – A label on every node, giving the distance from S to that node
Breadth-First-Search Visit node according to its layer procedure bfs(G, s) //Input: Graph G = (V,E), directed or undirected; vertex s V //Output: visit[u] is set to true for all nodes u reachable from v for each v V visited[v] = false visited[s] = true Queue Q = [s] //queue containing just s while Q is not empty v = Q.dequeue() previsit(v) visited[v] = true for each edge (v,u) E if not visited[u] visited[u] = true Q.enqueue(u) postvisit(v)
Distance using BFS procedure shortest_bfs(G, s) //Input: Graph G = (V,E), directed or undirected; vertex s V //Output: For all vertices u reachable from s, dist(u) is set to the distance from s to u. for all v V dist[v] = -1 dist[s] = 0 Queue Q = [s] //queue containing just s while Q is not empty v = Q.dequeue() for all edges (v,u) E if dist[u] = -1 dist[u] = dist[v] + 1 Q.enqueue(u) Use dist as visited
DFS by Stack procedure dfs(G, s) //Input: Graph G = (V,E), directed or undirected; vertex s V //Output: visited[u] is true for any node u reachable from v for each v V visited[v] = false visited[s] = true Stack S = [s] //queue containing just s while S is not empty v = S.pop() previsit(v) visited[v] = true for each edge (v,u) E if not visited[u] visited[u] = true S.push(u) postvisit(v)
DFS vs BFS DFS goes depth first – Trying to go further if possible – Backtrack only when no other possible way to go – Using Stack BFS goes breadth first – Trying to visit node by the distance from the starting node – Using Queue