[Algo] Graph Traversal

DFS Traversal

Basic structure

  • Greedily visit all the child nodes of a child node before going to the next child node.
  • Use a vis vector to record all visited nodes.
void DFS(int cur ...) {
  if (vis[cur]) return;

  // visit all child nodes
  for (auto next:graph[cur]) {
    DFS(next ...);
  }
}

for (int i=0;i<n;++i) {
  DFS(i ...);
}

Ordering in DFS

  • During the DFS traversal, we can give a timestamp to each node and order them.
  • Preorder timestamp
    • Finding cut-vertex and cut-edge in Undirected Graph. In the DFS search tree, a smaller timestamp node can always to a large timestamp node following the traverse path. If we find a node, without backtracking the traverse path, cannot go to a smaller timestamp node, it means that the node’s subtree cannot go to any ancestor of the node. Therefore, removing this node, or removing the last edge of the traverse path, will disconnect the node’s subtree and the node’s ancestors.
  • Postorder timestamp
    • Topological sorting in Directed Graph. During the traversal, if there is no loop, then the reverse of postorder sorting is a topological sorting. This is because in post ordering, we always visit all children nodes first, then the root node. Therefore, its reverse will always visit root node first before child nodes.
void DFS(int cur ...) {
  if (vis[cur]) return;

  // visit current node
  preorder_timestamp[cur] = cur_time;
  preorder_nodes.push_back(cur);
  preorder_cur_time++;

  // visit all child nodes
  for (auto next:graph[cur]) {
    DFS(next ...);
  }

  // backtrack to current node
  postorder_timestamp[cur] = cur_time;
  postorder_nodes.push_back(cur);
  postorder_cur_time++;
}

Coloring in DFS traversal

  • We can color visited node differently during the traversal.
  • Checking bipartite graph: we can alter the color of node during the traversal. If we find two adjacent nodes have same color, we return fasle.
  • Checking loop in directed graph: In directed graph, only when a node connect to the current traverse path, it will be considered a loop. The color of node can be used to distinguish, if a node is in the current traverse path, or a previously already back-tracked traverse path.
void DFS(int cur ...) {
  if (color[cur]==1 || color[cur]==2) return;

  // visit current node
  color[cur] = 1;

  // visit all child nodes
  for (auto next:graph[cur]) {
    DFS(next ...);
  }

  // back track to current node
  color[cur] = 2;
}

DP in DFS traversal

  • DFS implies a search tree. If there is no loop, we can conduct a dp algorithm based on the search tree structure.
void DFS(int cur ...) {
  if (vis[cur]) return;
  
  for (auto next:graph[cur]) {
    DFS(next ...);
  }

  // Aggregates all children dp value to current dp value
  dp[cur] = aggregate(dp[next1], dp[next2] ...);
}

BFS Traversal

  • BFS can traverse nodes by one layer after another layer
  • Coloring in BFS: we can alternatively color nodes in different layer differently. By this, we can check if the graph is bipartite.
  • State in BFS: by maintaining a visited vector, we can find loop in an undirected graph.
  • Ordering in BFS: removing zero in-degree nodes one by one, we can find the topological sorted order.
  • DP in BFS: following the topological sorted order, we can calculate a successor’s DP value based on all its ancestors’ DP value.
while (!q.empty()) {
  int sz=q.size();
  for (int i=0;i<sz;++i) {
    // visit current node
    int cur = q.front(); q.pop();
    vis[cur] = true;

    // add successor nodes
    for (auto next:graph[cur]) {
      if (vis[next]) continue;
      q.push(next);
    }
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *