📜  使用拓扑排序检测有向图中的周期

📅  最后修改于: 2021-04-29 14:41:43             🧑  作者: Mango

给定一个有向图,包括N个顶点和M的边缘和一组[] [],任务是检查图形是否包含周期或不使用拓扑排序。

例子:

方法:
在“拓扑排序”中,其想法是先访问父节点,再访问子节点。如果给定的图包含一个循环,则至少有一个节点既是父节点又是子节点,因此这将破坏拓扑顺序。因此,在拓扑排序之后,检查每个有向边是否遵循顺序。

下面是上述方法的实现:

C++
// C++ Program to implement
// the above approach
#include 
using namespace std;
 
int t, n, m, a;
 
// Stack to store the
// visited vertices in
// the Topological Sort
stack s;
 
// Store Topological Order
vector tsort;
 
// Adjacency list to store edges
vector adj[int(1e5) + 1];
 
// To ensure visited vertex
vector visited(int(1e5) + 1);
 
// Function to perform DFS
void dfs(int u)
{
    // Set the vertex as visited
    visited[u] = 1;
 
    for (auto it : adj[u]) {
 
        // Visit connected vertices
        if (visited[it] == 0)
            dfs(it);
    }
 
    // Push into the stack on
    // complete visit of vertex
    s.push(u);
}
 
// Function to check and return
// if a cycle exists or not
bool check_cycle()
{
    // Stores the position of
    // vertex in topological order
    unordered_map pos;
    int ind = 0;
 
    // Pop all elements from stack
    while (!s.empty()) {
        pos[s.top()] = ind;
 
        // Push element to get
        // Topological Order
        tsort.push_back(s.top());
 
        ind += 1;
 
        // Pop from the stack
        s.pop();
    }
 
    for (int i = 0; i < n; i++) {
        for (auto it : adj[i]) {
 
            // If parent vertex
            // does not appear first
            if (pos[i] > pos[it]) {
 
                // Cycle exists
                return true;
            }
        }
    }
 
    // Return false if cycle
    // does not exist
    return false;
}
 
// Function to add edges
// from u to v
void addEdge(int u, int v)
{
    adj[u].push_back(v);
}
 
// Driver Code
int main()
{
    n = 4, m = 5;
 
    // Insert edges
    addEdge(0, 1);
    addEdge(0, 2);
    addEdge(1, 2);
    addEdge(2, 0);
    addEdge(2, 3);
 
    for (int i = 0; i < n; i++) {
        if (visited[i] == 0) {
            dfs(i);
        }
    }
 
    // If cycle exist
    if (check_cycle())
        cout << "Yes";
    else
        cout << "No";
 
    return 0;
}


Java
// Java program to implement
// the above approach
import java.util.*;
 
class GFG{
     
static int t, n, m, a;
 
// Stack to store the
// visited vertices in
// the Topological Sort
static Stack s;
 
// Store Topological Order
static ArrayList tsort;
 
// Adjacency list to store edges
static ArrayList> adj;
 
// To ensure visited vertex
static int[] visited = new int[(int)1e5 + 1];
 
// Function to perform DFS
static void dfs(int u)
{
     
    // Set the vertex as visited
    visited[u] = 1;
 
    for(Integer it : adj.get(u))
    {
         
        // Visit connected vertices
        if (visited[it] == 0)
            dfs(it);
    }
     
    // Push into the stack on
    // complete visit of vertex
    s.push(u);
}
 
// Function to check and return
// if a cycle exists or not
static boolean check_cycle()
{
     
    // Stores the position of
    // vertex in topological order
    Map pos = new HashMap<>();
     
    int ind = 0;
     
    // Pop all elements from stack
    while (!s.isEmpty())
    {
        pos.put(s.peek(), ind);
         
        // Push element to get
        // Topological Order
        tsort.add(s.peek());
 
        ind += 1;
         
        // Pop from the stack
        s.pop();
    }
 
    for(int i = 0; i < n; i++)
    {
        for(Integer it : adj.get(i))
        {
             
            // If parent vertex
            // does not appear first
            if (pos.get(i) > pos.get(it))
            {
                 
                // Cycle exists
                return true;
            }
        }
    }
 
    // Return false if cycle
    // does not exist
    return false;
}
 
// Function to add edges
// from u to v
static void addEdge(int u, int v)
{
    adj.get(u).add(v);
}
 
// Driver code   
public static void main (String[] args)
{
    n = 4; m = 5;
     
    s = new Stack<>();
    adj = new ArrayList<>();
    tsort = new ArrayList<>();
     
    for(int i = 0; i < 4; i++)
        adj.add(new ArrayList<>());
         
    // Insert edges
    addEdge(0, 1);
    addEdge(0, 2);
    addEdge(1, 2);
    addEdge(2, 0);
    addEdge(2, 3);
     
    for(int i = 0; i < n; i++)
    {
        if (visited[i] == 0)
        {
            dfs(i);
        }
    }
     
    // If cycle exist
    if (check_cycle())
       System.out.println("Yes");
    else
       System.out.println("No");
}
}
 
// This code is contributed by offbeat


Python3
# Python3 program to implement
# the above approach
t = 0
n = 0
m = 0
a = 0
  
# Stack to store the
# visited vertices in
# the Topological Sort
s = []
  
# Store Topological Order
tsort = []
  
# Adjacency list to store edges
adj = [[] for i in range(100001)]
  
# To ensure visited vertex
visited = [False for i in range(100001)]
  
# Function to perform DFS
def dfs(u):
 
    # Set the vertex as visited
    visited[u] = 1
     
    for it in adj[u]:
 
        # Visit connected vertices
        if (visited[it] == 0):
            dfs(it)
  
    # Push into the stack on
    # complete visit of vertex
    s.append(u)
 
# Function to check and return
# if a cycle exists or not
def check_cycle():
 
    # Stores the position of
    # vertex in topological order
    pos = dict()
     
    ind = 0
     
    # Pop all elements from stack
    while (len(s) != 0):
        pos[s[-1]] = ind
  
        # Push element to get
        # Topological Order
        tsort.append(s[-1])
  
        ind += 1
  
        # Pop from the stack
        s.pop()
     
    for i in range(n):
        for it in adj[i]:
            first = 0 if i not in pos else pos[i]
            second = 0 if it not in pos else pos[it]
 
            # If parent vertex
            # does not appear first
            if (first > second):
  
                # Cycle exists
                return True
  
    # Return false if cycle
    # does not exist
    return False
 
# Function to add edges
# from u to v
def addEdge(u, v):
     
    adj[u].append(v)
 
# Driver Code
if __name__ == "__main__":
     
    n = 4
    m = 5
  
    # Insert edges
    addEdge(0, 1)
    addEdge(0, 2)
    addEdge(1, 2)
    addEdge(2, 0)
    addEdge(2, 3)
     
    for i in range(n):
        if (visited[i] == False):
            dfs(i)
  
    # If cycle exist
    if (check_cycle()):
        print('Yes')
    else:
        print('No')
         
# This code is contributed by rutvik_56


C#
// C# program to implement
// the above approach
using System;
using System.Collections;
using System.Collections.Generic;
  
class GFG{
 
static int n;
  
// Stack to store the
// visited vertices in
// the Topological Sort
static Stack s;
  
// Store Topological Order
static ArrayList tsort;
  
// Adjacency list to store edges
static ArrayList adj;
  
// To ensure visited vertex
static int[] visited = new int[100001];
  
// Function to perform DFS
static void dfs(int u)
{
     
    // Set the vertex as visited
    visited[u] = 1;
  
    foreach(int it in (ArrayList)adj[u])
    {
         
        // Visit connected vertices
        if (visited[it] == 0)
            dfs(it);
    }
      
    // Push into the stack on
    // complete visit of vertex
    s.Push(u);
}
  
// Function to check and return
// if a cycle exists or not
static bool check_cycle()
{
     
    // Stores the position of
    // vertex in topological order
    Dictionary pos = new Dictionary();
      
    int ind = 0;
      
    // Pop all elements from stack
    while (s.Count != 0)
    {
        pos.Add(s.Peek(), ind);
         
        // Push element to get
        // Topological Order
        tsort.Add(s.Peek());
  
        ind += 1;
          
        // Pop from the stack
        s.Pop();
    }
  
    for(int i = 0; i < n; i++)
    {
        foreach(int it in (ArrayList)adj[i])
        {
             
            // If parent vertex
            // does not appear first
            if (pos[i] > pos[it])
            {
                 
                // Cycle exists
                return true;
            }
        }
    }
  
    // Return false if cycle
    // does not exist
    return false;
}
  
// Function to add edges
// from u to v
static void addEdge(int u, int v)
{
    ((ArrayList)adj[u]).Add(v);
}
  
// Driver code   
public static void Main(string[] args)
{
    n = 4;
      
    s = new Stack();
    adj = new ArrayList();
    tsort = new ArrayList();
      
    for(int i = 0; i < 4; i++)
        adj.Add(new ArrayList());
          
    // Insert edges
    addEdge(0, 1);
    addEdge(0, 2);
    addEdge(1, 2);
    addEdge(2, 0);
    addEdge(2, 3);
      
    for(int i = 0; i < n; i++)
    {
        if (visited[i] == 0)
        {
            dfs(i);
        }
    }
      
    // If cycle exist
    if (check_cycle())
       Console.WriteLine("Yes");
    else
       Console.WriteLine("No");
}
}
 
// This code is contributed by pratham76


输出:
Yes

时间复杂度: O(N + M)
辅助空间: O(N)