给定一个有向图,包括N个顶点和M的边缘和一组边的[] [],任务是检查图形是否包含周期或不使用拓扑排序。
Topological sort of directed graph is a linear ordering of its vertices such that, for every directed edge U -> V from vertex U to vertex V, U comes before V in the ordering.
例子:
Input: N = 4, M = 6, Edges[][] = {{0, 1}, {1, 2}, {2, 0}, {0, 2}, {2, 3}, {3, 3}}
Output: Yes
Explanation:
A cycle 0 -> 2 -> 0 exists in the given graph
Input: N = 4, M = 3, Edges[][] = {{0, 1}, {1, 2}, {2, 3}, {0, 2}}
Output: No
方法:
在“拓扑排序”中,其想法是先访问父节点,再访问子节点。如果给定的图包含一个循环,则至少有一个节点既是父节点又是子节点,因此这将破坏拓扑顺序。因此,在拓扑排序之后,检查每个有向边是否遵循顺序。
下面是上述方法的实现:
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)