Open In App

Find the Dominators for every vertex in a given DAG (Directed Acyclic Graph)

Last Updated : 19 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given a Directed Acyclic Graph with V vertices and E edges, the task is to find the set of dominant vertices for each vertex of the graph.

What are Dominators in Graph Theory: In control flow graphs a vertex V1 is the dominator of another vertex V2 if all the paths from the source vertex (in this case the vertex ‘0’) to the vertex V2 passes through V1. By definition, every vertex is one of its own dominators.

Examples:

Input: V = 5, E = 5, adj[][] = {{0, 1}, {0, 2}, {1, 3}, {2, 3}, {3, 4}}
Output:
Dominating set of vertex: 0 –> 0 
Dominating set of vertex: 1 –> 0 1 
Dominating set of vertex: 2 –> 0 2 
Dominating set of vertex: 3 –> 0 3 
Dominating set of vertex: 4 –> 0 3 4
Explanation:
          0
       /     \
     1        2
      \      /
         3
         |
        4          
Here 0 is the entry node, so its dominator is 0 itself.
Only one path exists between (0, 1) so the dominators of 1 are 0, 1.
Only one path exists between (0, 2) so the dominators of 2 are 0, 2.
There are 2 paths between(0, 3) having only 0, 3 in common.
From (0, 4) there are 2 paths (0 1 3 4) and (0 2 3 4) with 0, 3 and 4 common.

Input: V = 4, E = 3, adj[][] = {{0, 1}, {0, 2}, {3, 2}}
Output:
Dominating set of vertex: 0 –> 0 
Dominating set of vertex: 1 –> 0 1 
Dominating set of vertex: 2 –> 0 2 
Dominating set of vertex: 3 –> 0 2 3

Approach: The idea is to perform DFS and maintain a set of all the dominators of each vertex. Follow the steps below to solve the problem:

  • Graph Traversal and Postorder: Perform a DFS from the source node (usually node 0) to obtain a postorder of the vertices. This will help process the vertices in reverse order.
  • Initialize Dominators: Initialize the dominators for each vertex. The entry vertex (source vertex) should dominate only itself. For all other vertices, their initial dominators should include all vertices in the graph.
  • Iterative Process: Repeat the following process until there is no change in the dominators for any vertex:
  • For each vertex v in postorder (starting from the entry point), calculate its dominators as the intersection of its predecessors’ dominators, adding itself to the intersection result.
  • Update the dominator set for each vertex.
  • Calculate Intersection: Calculate the intersection of dominators of each vertex’s predecessors and add the current vertex to its dominator set.
  • Repeat Until No Changes: Keep iterating until no changes are made to any vertex’s dominator set.
  • Output: Once the process completes, output the set of dominators for each vertex.

Below is the implementation of the above approach:

Java
import java.util.*;

public class Dominators {
    public static void findDominators(int V, int[][] edges) {
        // Initialize graph
        Map<Integer, List<Integer>> graph = new HashMap<>();
        for (int[] edge : edges) {
            graph.computeIfAbsent(edge[0], k -> new ArrayList<>()).add(edge[1]);
        }
        
        // Initialize the list of dominators
        List<Set<Integer>> dominators = new ArrayList<>(V);
        for (int i = 0; i < V; i++) {
            dominators.add(new HashSet<>());
        }
        
        // Initialize a list of incoming edges count for each vertex
        int[] inDegrees = new int[V];
        for (int[] edge : edges) {
            inDegrees[edge[1]]++;
        }
        
        // Initialize the dominator set for the entry node (source node 0)
        dominators.get(0).add(0);
        
        // Initialize a queue for BFS traversal
        Queue<Integer> queue = new LinkedList<>();
        queue.add(0);
        
        // Perform BFS
        while (!queue.isEmpty()) {
            int u = queue.poll();
            
            // Traverse neighbors of the current vertex
            for (int v : graph.getOrDefault(u, new ArrayList<>())) {
                // Calculate the intersection of dominators from all predecessors of v
                if (dominators.get(v).isEmpty()) {
                    dominators.get(v).addAll(dominators.get(u));
                    dominators.get(v).add(v);
                } else {
                    dominators.get(v).retainAll(dominators.get(u));
                }
                
                // Reduce the in-degree count for vertex v
                inDegrees[v]--;
                
                // If all predecessors of v have been processed, add v to the queue
                if (inDegrees[v] == 0) {
                    queue.add(v);
                }
            }
        }
        
        // Print the dominator sets for each vertex
        for (int i = 0; i < V; i++) {
            System.out.print("Dominating set of vertex " + i + ": ");
            List<Integer> sortedDominators = new ArrayList<>(dominators.get(i));
            Collections.sort(sortedDominators);
            for (int dominator : sortedDominators) {
                System.out.print(dominator + " ");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        int V = 5;
        int[][] edges = {{0, 1}, {0, 2}, {1, 3}, {2, 3}, {3, 4}};
        findDominators(V, edges);
    }
}
Python3
from collections import defaultdict, deque

def find_dominators(V, edges):
    # Initialize graph
    graph = defaultdict(list)
    for u, v in edges:
        graph[u].append(v)
    
    # Initialize the list of dominators
    dominators = [set() for _ in range(V)]
    
    # Initialize a list of incoming edges count for each vertex
    in_degrees = [0] * V
    for u, v in edges:
        in_degrees[v] += 1
    
    # Initialize the dominator set for the entry node (source node 0)
    dominators[0] = {0}
    
    # Initialize a queue for BFS traversal
    queue = deque([0])
    
    # Perform BFS
    while queue:
        u = queue.popleft()
        
        # Traverse neighbors of current vertex
        for v in graph[u]:
            # Calculate the intersection of dominators from all predecessors of v
            if not dominators[v]:
                dominators[v] = dominators[u].copy()
                dominators[v].add(v)
            else:
                dominators[v].intersection_update(dominators[u])
            
            # Reduce the in-degree count for vertex v
            in_degrees[v] -= 1
            
            # If all predecessors of v have been processed, add v to the queue
            if in_degrees[v] == 0:
                queue.append(v)
    
    # Print the dominator sets for each vertex
    for i in range(V):
        print(f"Dominating set of vertex {i}: {sorted(dominators[i])}")

# Example usage:
V = 5
edges = [(0, 1), (0, 2), (1, 3), (2, 3), (3, 4)]
find_dominators(V, edges)
C#
using System;
using System.Collections.Generic;

public class Dominators
{
    public static void FindDominators(int V, int[][] edges)
    {
        // Initialize graph
        Dictionary<int, List<int>> graph = new Dictionary<int, List<int>>();
        foreach (var edge in edges)
        {
            if (!graph.ContainsKey(edge[0]))
                graph[edge[0]] = new List<int>();
            graph[edge[0]].Add(edge[1]);
        }
        
        // Initialize the list of dominators
        List<HashSet<int>> dominators = new List<HashSet<int>>(V);
        for (int i = 0; i < V; i++)
        {
            dominators.Add(new HashSet<int>());
        }
        
        // Initialize a list of incoming edges count for each vertex
        int[] inDegrees = new int[V];
        foreach (var edge in edges)
        {
            inDegrees[edge[1]]++;
        }
        
        // Initialize the dominator set for the entry node (source node 0)
        dominators[0].Add(0);
        
        // Initialize a queue for BFS traversal
        Queue<int> queue = new Queue<int>();
        queue.Enqueue(0);
        
        // Perform BFS
        while (queue.Count > 0)
        {
            int u = queue.Dequeue();
            
            // Traverse neighbors of the current vertex
            if (graph.TryGetValue(u, out var neighbors))
            {
                foreach (var v in neighbors)
                {
                    // Calculate the intersection of dominators from all predecessors of v
                    if (dominators[v].Count == 0)
                    {
                        dominators[v].UnionWith(dominators[u]);
                        dominators[v].Add(v);
                    }
                    else
                    {
                        dominators[v].IntersectWith(dominators[u]);
                    }
                    
                    // Reduce the in-degree count for vertex v
                    inDegrees[v]--;
                    
                    // If all predecessors of v have been processed, add v to the queue
                    if (inDegrees[v] == 0)
                    {
                        queue.Enqueue(v);
                    }
                }
            }
        }
        
        // Print the dominator sets for each vertex
        for (int i = 0; i < V; i++)
        {
            Console.Write($"Dominating set of vertex {i}: ");
            var sortedDominators = new List<int>(dominators[i]);
            sortedDominators.Sort();
            foreach (var dominator in sortedDominators)
            {
                Console.Write(dominator + " ");
            }
            Console.WriteLine();
        }
    }

    public static void Main()
    {
        int V = 5;
        int[][] edges = new int[][] { new int[] { 0, 1 }, new int[] { 0, 2 }, new int[] { 1, 3 }, new int[] { 2, 3 }, new int[] { 3, 4 } };
        FindDominators(V, edges);
    }
}
Javascript
function findDominators(V, edges) {
    // Initialize graph
    const graph = {};
    for (const [u, v] of edges) {
        if (!graph[u]) graph[u] = [];
        graph[u].push(v);
    }

    // Initialize the list of dominators
    const dominators = Array.from({ length: V }, () => new Set());

    // Initialize a list of incoming edges count for each vertex
    const inDegrees = new Array(V).fill(0);
    for (const [u, v] of edges) {
        inDegrees[v]++;
    }

    // Initialize the dominator set for the entry node (source node 0)
    dominators[0].add(0);

    // Initialize a queue for BFS traversal
    const queue = [0];

    // Perform BFS
    while (queue.length > 0) {
        const u = queue.shift();

        // Traverse neighbors of the current vertex
        if (graph[u]) {
            for (const v of graph[u]) {
                // Calculate the intersection of dominators from all predecessors of v
                if (dominators[v].size === 0) {
                    dominators[v] = new Set([...dominators[u]]);
                    dominators[v].add(v);
                } else {
                    dominators[v] = new Set([...dominators[v]].filter(val => dominators[u].has(val)));
                }
                
                // Reduce the in-degree count for vertex v
                inDegrees[v]--;

                // If all predecessors of v have been processed, add v to the queue
                if (inDegrees[v] === 0) {
                    queue.push(v);
                }
            }
        }
    }

    // Print the dominator sets for each vertex
    for (let i = 0; i < V; i++) {
        console.log(`Dominating set of vertex ${i}: ${[...dominators[i]].sort().join(' ')}`);
    }
}

// Example usage:
const V = 5;
const edges = [[0, 1], [0, 2], [1, 3], [2, 3], [3, 4]];
findDominators(V, edges);
C++14
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <set>
#include <algorithm>

using namespace std;

void findDominators(int V, const vector<pair<int, int>>& edges) {
    // Initialize graph
    unordered_map<int, vector<int>> graph;
    for (const auto& edge : edges) {
        graph[edge.first].push_back(edge.second);
    }
    
    // Initialize the list of dominators
    vector<set<int>> dominators(V);
    
    // Initialize a list of incoming edges count for each vertex
    vector<int> inDegrees(V, 0);
    for (const auto& edge : edges) {
        inDegrees[edge.second]++;
    }
    
    // Initialize the dominator set for the entry node (source node 0)
    dominators[0].insert(0);
    
    // Initialize a queue for BFS traversal
    queue<int> q;
    q.push(0);
    
    // Perform BFS
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        
        // Traverse neighbors of the current vertex
        for (int v : graph[u]) {
            // Calculate the intersection of dominators from all predecessors of v
            if (dominators[v].empty()) {
                dominators[v] = dominators[u];
                dominators[v].insert(v);
            } else {
                set<int> intersection;
                set_intersection(
                    dominators[v].

Output
0 -> 0 
1 -> 0 1 
2 -> 0 2 
3 -> 0 3 
4 -> 0 3 4 

Time Complexity: O(V + E)
Auxiliary Space: O(V2)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads