Skip to main content

Graph

The adjacvency-list representation of a graph G=(V,E)G = (V,E) consists of an array Adj , one for each vertex in VV. For each uVu\in V, the adjacency list Adj[u]Adj[u] contains all the vertices ν\nu such that (u,ν)E(u,\nu)\in E.

  • Use space complexity O(V+E)O(|V|+|E|)

The adjacency-matrix representation of a graph G=(V,E)G = (V,E) consists of a matrix AdjAdj such that Adj[u][v]Adj[u][v] is 1 if (u,v)E(u,v)\in E and 0 otherwise where this such matrix is V×V|V|\times|V|.

  • Use space complexity O(V2)O(|V|^2)

We always prefer the adjacency-list representation of a graph because it is more space-efficient than the adjacency-matrix representation and get more rubustness in which we can augment on the node of the linked list so that we can present weight graph.

For a graph G=(V,E)G = (V,E) and a start vertex sVs\in V, the breadth-first search of GG from ss is a traversal of the graph that visits each vertex uVu\in V exactly once and for each edge (u,v)E(u,v)\in E exactly once (may not traversal all). Such traversal graph is called a breadth-first tree. Moreover, we do color each vertex uVu\in V as white, gray, or black. We start with ss as gray and all other vertices as white. We then visit each vertex uVu\in V exactly once and for each edge (u,v)E(u,v)\in E exactly once. Once all adjacent vertices of uu are visited, we color uu as black. We do this by maintaining a queue QQ of vertices that we have discovered but not yet visited. Initially, QQ contains only ss.

The total run-time of BFS is O(V+E)O(|V|+|E|) where the initialization takes O(V)O(|V|) time and scanning all the edges takes O(E)O(|E|) time.

Some problems can be solved by BFS: shortest path, connected components, bipartite, two-colorability, etc.

  • shortest path: we do BFS and return the degree of the target node. If we can successfully reach the target node, we will update the degree of the target node. Otherwise, we will see its degree is infinity which is the default value.

For a graph G=(V,E)G = (V,E) and a start vertex sVs\in V, we define predecessor subgraph of GG from ss where Gs=(Vs,Es)G_s = (V_s,E_s) such that Vs={vVv.πNIL}{s}V_s = \{v\in V|v.\pi \ne \text{NIL}\} \cup \{s\} and Es={(v.π,v)vVs{s}}E_s = \{(v.\pi,v)|v\in V_s - \{s\}\}. Such subgraph is breath-first tree if VsV_s contains all reachable vertices from ss and vVs\forall v\in V_s there is a unique path from ss to vv in GsG_s (also is the shortest path from ss to vv).

The BFS algorithm take O(V+E)O(|V|+|E|) time.

We also define the shortest-path distance δ(s,v)\delta(s,v) from ss to vv in GG as the length of the shortest path from ss to vv in GG.

The predecessor subgraph of a DFS froms a depth-first forest comprising several depth-first trees. We also do timestamps for each vertex which notice the arrival time and finished time. (u.d denote discovered time which start from parent time + 1, u.f denote finished time which end with the last child time + 1). According the time structure we have properties, for a node u,vu, v:

  • if [u.d,u.f][u.d, u.f] and [v.d,v.f][v.d, v.f] are disjoint, then uu and vv are not a descendant of each other in the depth-first forest.
  • if [u.d,u.f][u.d, u.f] is a subset of [v.d,v.f][v.d, v.f], then uu is a descendant of vv in the depth-first forest.

We also define several edges of depth-first forest:

  • tree edge: an edge (u,v)E(u,v)\in E such that v.π=uv.\pi = u.
  • back edge: an edge (u,v)E(u,v) \in E, such that v.d<u.dv.d < u.d and v.f>u.fv.f > u.f. Self-loop is also a back edge.
  • forward edge: an edge (u,v)E(u,v) \in E such that v.d>u.dv.d > u.d and v.f<u.fv.f < u.f.
  • cross edge: all other edges.

An undirected graph GG, every edge of GG is either a tree edge or a back edge.

The DFS algorithm take O(V+E)O(|V|+|E|) time.

Topological Sort

A topological sort of a directed acyclic graph G=(V,E)G = (V,E) is a linear ordering of all its vertices such that if (u,v)E(u,v)\in E, then uu appears before vv in the ordering. We can use DFS to find a topological sort of a directed acyclic graph G=(V,E)G = (V,E). Steps with precondition DAG G=(V,E)G = (V,E):

  1. Call DFS(G) to compute finishing times v.fv.f for each vertex vv.
  2. as each vertex is finished, insert it onto the front of a linked list.
  3. return the linked list of vertices.

A directed graph GG is acyclic     \iff a depth-first search of GG never produces a back edge.

The topological sort algorithm take O(V+E)O(|V|+|E|) time.

Strongly Connected Components

A directed graph G=(V,E)G = (V,E) is strongly connected     \iff for every pair of vertices u,vVu,v\in V, there is a path from uu to vv and a path from vv to uu.

Using Edge and Transpose Edge, we can find the strongly connected components of a directed graph G=(V,E)G = (V,E).

Steps:

  1. Call DFS(G) to compute finishing times v.fv.f for each vertex vv.
  2. compute GTG^T.
  3. call DFS(G^T), but in the main loop of DFS, consider the vertices in order of decreasing v.fv.f (as computed in line 1).
  4. output the vertices of each tree in the depth-first forest formed in line 3 as a separate strongly connected component.

Component Graph: Suppose GG has C1,,CkC_1, \ldots, C_k strongly connected components. Then we define VSCC={v1,,vk}V^{SCC} = \{v_1,\ldots,v_k\} and vVSCC\forall v\in V^{SCC}, viv_i is the representative of CiC_i. We define ESCC={(vi,vj)uCi,vCj,(u,v)E}E^{SCC} = \{(v_i,v_j)|\exists u\in C_i, v\in C_j, (u,v)\in E\}. Then GSCC=(VSCC,ESCC)G^{SCC} = (V^{SCC}, E^{SCC}) is a directed acyclic graph.

Let CC and CC' be distinct strongly connected components in directed graph GG. Let u,vCu,v\in C and u,vCu',v'\in C', and suppose GG contains a path from uu to uu', then GG cannot also contain a path from vv‘ to vv.

Let CC and CC' be distinct strongly connected components in directed graph GG. Suppose edge (u,v)E(u,v)\in E where uCu\in C, vCv\in C'. Then f(C)f(C)f(C) \ge f(C').