📌  相关文章
📜  不属于有向图的任何循环的打印节点

📅  最后修改于: 2021-05-13 22:46:58             🧑  作者: Mango

给定一个有向图,G N个节点和E Edges由值[0,N – 1]的节点和类型为{ uv }的2D数组Edges [] [2]组成,表示顶点uv之间的有向边。任务是在给定图G中找到不属于任何循环的节点。

例子:

天真的方法:最简单的方法是为给定图中的每个节点检测有向图中的一个循环,并仅打印不属于给定图中任何循环一部分的那些节点。
时间复杂度: O(V *(V + E)),其中V是顶点数,E是边数。
辅助空间: O(V)

高效方法:为了优化上述方法,其思想是在给定图中的任何周期时,将中间节点存储为访问周期节点。要实现此部分,请使用辅助数组cyclePart [] ,该数组将在执行DFS遍历时存储中间循环节点。步骤如下:

  • 初始化大小为N的辅助数组cyclePart [] ,以便如果cyclePart [i] = 0 ,则i节点在任何循环中都不存在。
  • 初始化大小为N的辅助数组recStack [] ,以便通过将访问的节点标记为true来将访问的节点存储在递归堆栈中。
  • 在给定的图形上对每个未访问的节点执行DFS遍历,然后执行以下操作:
    • 现在找到在给定的图中,每当一个周期被发现一个周期,标志着cyclePart [],节点为此节点是周期的一部分。
    • 如果在递归调用中访问了任何节点,并且recStack [node]也为true,则该节点是循环的一部分,然后将该节点标记为true
  • 执行DFS遍历后,遍历数组cyclePart []并打印所有标记为false的节点,因为这些节点不是任何循环的一部分。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
class Graph {
 
    // No. of vertices
    int V;
 
    // Stores the Adjacency List
    list* adj;
    bool printNodesNotInCycleUtil(
        int v, bool visited[], bool* rs,
        bool* cyclePart);
 
public:
    // Constructor
    Graph(int V);
 
    // Member Functions
    void addEdge(int v, int w);
    void printNodesNotInCycle();
};
 
// Function to initialize the graph
Graph::Graph(int V)
{
    this->V = V;
    adj = new list[V];
}
 
// Function that adds directed edges
// between node v with node w
void Graph::addEdge(int v, int w)
{
    adj[v].push_back(w);
}
 
// Function to perform DFS Traversal
// and return true if current node v
// formes cycle
bool Graph::printNodesNotInCycleUtil(
    int v, bool visited[],
    bool* recStack, bool* cyclePart)
{
 
    // If node v is unvisited
    if (visited[v] == false) {
 
        // Mark the current node as
        // visited and part of
        // recursion stack
        visited[v] = true;
        recStack[v] = true;
 
        // Traverse the Adjacency
        // List of current node v
        for (auto& child : adj[v]) {
 
            // If child node is unvisited
            if (!visited[child]
                && printNodesNotInCycleUtil(
                       child, visited,
                       recStack, cyclePart)) {
 
                // If child node is a part
                // of cycle node
                cyclePart[child] = 1;
                return true;
            }
 
            // If child node is visited
            else if (recStack[child]) {
                cyclePart[child] = 1;
                return true;
            }
        }
    }
 
    // Remove vertex from recursion stack
    recStack[v] = false;
    return false;
}
 
// Function that print the nodes for
// the given directed graph that are
// not present in any cycle
void Graph::printNodesNotInCycle()
{
 
    // Stores the visited node
    bool* visited = new bool[V];
 
    // Stores nodes in recursion stack
    bool* recStack = new bool[V];
 
    // Stores the nodes that are
    // part of any cycle
    bool* cyclePart = new bool[V];
 
    for (int i = 0; i < V; i++) {
        visited[i] = false;
        recStack[i] = false;
        cyclePart[i] = false;
    }
 
    // Traverse each node
    for (int i = 0; i < V; i++) {
 
        // If current node is unvisited
        if (!visited[i]) {
 
            // Perform DFS Traversal
            if (printNodesNotInCycleUtil(
                    i, visited, recStack,
                    cyclePart)) {
 
                // Mark as cycle node
                // if it return true
                cyclePart[i] = 1;
            }
        }
    }
 
    // Traverse the cyclePart[]
    for (int i = 0; i < V; i++) {
 
        // If node i is not a part
        // of any cycle
        if (cyclePart[i] == 0) {
            cout << i << " ";
        }
    }
}
 
// Function that print the nodes for
// the given directed graph that are
// not present in any cycle
void solve(int N, int E,
           int Edges[][2])
{
 
    // Initialize the graph g
    Graph g(N);
 
    // Create a directed Graph
    for (int i = 0; i < E; i++) {
        g.addEdge(Edges[i][0],
                  Edges[i][1]);
    }
 
    // Function Call
    g.printNodesNotInCycle();
}
 
// Driver Code
int main()
{
    // Given Number of nodes
    int N = 6;
 
    // Given Edges
    int E = 7;
 
    int Edges[][2] = { { 0, 1 }, { 0, 2 },
                       { 1, 3 }, { 2, 1 },
                       { 2, 5 }, { 3, 0 },
                                 { 4, 5 } };
 
    // Function Call
    solve(N, E, Edges);
 
    return 0;
}


Java
// Java program for above approach
import java.util.*;
import java.lang.*;
class GFG
{
 
  static ArrayList> adj;
  static int V;
 
  // Function to perform DFS Traversal
  // and return true if current node v
  // formes cycle
  static boolean printNodesNotInCycleUtil(
    int v, boolean visited[],
    boolean[] recStack, boolean[] cyclePart)
  {
 
    // If node v is unvisited
    if (visited[v] == false)
    {
 
      // Mark the current node as
      // visited and part of
      // recursion stack
      visited[v] = true;
      recStack[v] = true;
 
      // Traverse the Adjacency
      // List of current node v
      for (Integer child : adj.get(v))
      {
 
        // If child node is unvisited
        if (!visited[child]
            && printNodesNotInCycleUtil(
              child, visited,
              recStack, cyclePart))
        {
 
          // If child node is a part
          // of cycle node
          cyclePart[child] = true;
          return true;
        }
 
        // If child node is visited
        else if (recStack[child])
        {
          cyclePart[child] = true;
          return true;
        }
      }
    }
 
    // Remove vertex from recursion stack
    recStack[v] = false;
    return false;
  }
 
  static void printNodesNotInCycle()
  {
 
    // Stores the visited node
    boolean[] visited = new boolean[V];
 
    // Stores nodes in recursion stack
    boolean[] recStack = new boolean[V];
 
    // Stores the nodes that are
    // part of any cycle
    boolean[] cyclePart = new boolean[V];
 
    // Traverse each node
    for (int i = 0; i < V; i++)
    {
 
      // If current node is unvisited
      if (!visited[i])
      {
 
        // Perform DFS Traversal
        if (printNodesNotInCycleUtil(
          i, visited, recStack,
          cyclePart)) {
 
          // Mark as cycle node
          // if it return true
          cyclePart[i] = true;
        }
      }
    }
 
    // Traverse the cyclePart[]
    for (int i = 0; i < V; i++)
    {
 
      // If node i is not a part
      // of any cycle
      if (!cyclePart[i])
      {
        System.out.print(i+" ");
      }
    }
  }
 
  // Function that print the nodes for
  // the given directed graph that are
  // not present in any cycle
  static void solve(int N, int E,
                    int Edges[][])
  {
 
    adj = new ArrayList<>();
 
    for(int i = 0; i < N; i++)
      adj.add(new ArrayList<>());
 
    // Create a directed Graph
    for (int i = 0; i < E; i++)
    {
      adj.get(Edges[i][0]).add(Edges[i][1]);
    }
 
    // Function Call
    printNodesNotInCycle();
  }
   
  // Driver function
  public static void main (String[] args)
  {
     
    // Given Number of nodes
    V = 6;
 
    // Given Edges
    int E = 7;
 
    int Edges[][] = { { 0, 1 }, { 0, 2 },
                     { 1, 3 }, { 2, 1 },
                     { 2, 5 }, { 3, 0 },
                     { 4, 5 } };
 
 
    // Function Call
    solve(V, E, Edges);
 
  }
}
 
// This code is contributed by offbeat


Python3
# Python3 program for the above approach
 
class Graph:
     
    # Function to initialize the graph
    def __init__(self, V):
         
        self.V = V
        self.adj = [[] for i in range(self.V)]
     
    # Function that adds directed edges
    # between node v with node w
    def addEdge(self, v, w):
     
        self.adj[v].append(w);
     
    # Function to perform DFS Traversal
    # and return True if current node v
    # formes cycle
    def printNodesNotInCycleUtil(self, v, visited,recStack, cyclePart):
     
        # If node v is unvisited
        if (visited[v] == False):
         
            # Mark the current node as
            # visited and part of
            # recursion stack
            visited[v] = True;
            recStack[v] = True;
     
            # Traverse the Adjacency
            # List of current node v
            for child in self.adj[v]:
             
                # If child node is unvisited
                if (not visited[child] and self.printNodesNotInCycleUtil(child, visited,recStack, cyclePart)):
                            
                    # If child node is a part
                    # of cycle node
                    cyclePart[child] = 1;
                    return True;
     
                # If child node is visited
                elif (recStack[child]):
                    cyclePart[child] = 1;
                    return True;
                     
        # Remove vertex from recursion stack
        recStack[v] = False;
        return False;
     
    # Function that print the nodes for
    # the given directed graph that are
    # not present in any cycle
    def printNodesNotInCycle(self):
     
        # Stores the visited node
        visited = [False for i in range(self.V)];
     
        # Stores nodes in recursion stack
        recStack = [False for i in range(self.V)];
     
        # Stores the nodes that are
        # part of any cycle
        cyclePart = [False for i in range(self.V)]
     
        # Traverse each node
        for i in range(self.V):
         
            # If current node is unvisited
            if (not visited[i]):
             
                # Perform DFS Traversal
                if(self.printNodesNotInCycleUtil(
                        i, visited, recStack,
                        cyclePart)):
                         
                    # Mark as cycle node
                    # if it return True
                    cyclePart[i] = 1;
     
        # Traverse the cyclePart[]
        for i in range(self.V):
         
            # If node i is not a part
            # of any cycle
            if (cyclePart[i] == 0) :
                print(i,end=' ')
                     
# Function that print the nodes for
# the given directed graph that are
# not present in any cycle
def solve( N, E, Edges):
 
    # Initialize the graph g
    g = Graph(N);
 
    # Create a directed Graph
    for i in range(E):
 
        g.addEdge(Edges[i][0],
                  Edges[i][1]);  
 
    # Function Call
    g.printNodesNotInCycle();   
     
    # Driver Code
if __name__=='__main__':
     
    # Given Number of nodes
    N = 6;
  
    # Given Edges
    E = 7;
  
    Edges = [ [ 0, 1 ], [ 0, 2 ],
                       [ 1, 3 ], [ 2, 1 ],
                       [ 2, 5 ], [ 3, 0 ],
                                 [ 4, 5 ] ];
  
    # Function Call
    solve(N, E, Edges);
   
# This code is contributed by rutvik_56


输出:
4 5

时间复杂度: O(V + E)
空间复杂度: O(V)