📜  使用 BFS 检测无向图中的循环

📅  最后修改于: 2022-05-13 01:57:54.333000             🧑  作者: Mango

使用 BFS 检测无向图中的循环

给定一个无向图,如何检查图中是否存在环?例如,下图有一个循环 1-0-2-1。

循环图

我们已经讨论了有向图的循环检测。我们还讨论了无向图中循环检测的联合查找算法。联合查找算法的时间复杂度为 O(ELogV)。像有向图一样,我们可以使用 DFS 在 O(V+E) 时间内检测无向图中的循环。我们已经讨论了基于 DFS 的无向图中循环检测的解决方案。
本文讨论了基于 BFS 的解决方案。我们对给定的图进行 BFS 遍历。对于每个访问过的顶点“v”,如果有一个相邻的“u”使得 u 已经被访问过并且 u 不是 v 的父级,则图中存在一个循环。如果我们没有为任何顶点找到这样的相邻点,我们就说没有循环。
我们使用父数组来跟踪顶点的父顶点,这样我们就不会将访问的父节点视为一个循环。

C++
// C++ program to detect cycle
// in an undirected graph
// using BFS.
#include 
using namespace std;
 
void addEdge(vector adj[], int u, int v)
{
    adj[u].push_back(v);
    adj[v].push_back(u);
}
 
bool isCyclicConntected(vector adj[], int s,
                        int V, vector& visited)
{
    // Set parent vertex for every vertex as -1.
    vector parent(V, -1);
 
    // Create a queue for BFS
    queue q;
 
    // Mark the current node as
    // visited and enqueue it
    visited[s] = true;
    q.push(s);
 
    while (!q.empty()) {
 
        // Dequeue a vertex from queue and print it
        int u = q.front();
        q.pop();
 
        // Get all adjacent vertices of the dequeued
        // vertex u. If a adjacent has not been visited,
        // then mark it visited and enqueue it. We also
        // mark parent so that parent is not considered
        // for cycle.
        for (auto v : adj[u]) {
            if (!visited[v]) {
                visited[v] = true;
                q.push(v);
                parent[v] = u;
            }
            else if (parent[u] != v)
                return true;
        }
    }
    return false;
}
 
bool isCyclicDisconntected(vector adj[], int V)
{
    // Mark all the vertices as not visited
    vector visited(V, false);
 
    for (int i = 0; i < V; i++)
        if (!visited[i] && isCyclicConntected(adj, i,
                                         V, visited))
            return true;
    return false;
}
 
// Driver program to test methods of graph class
int main()
{
    int V = 4;
    vector adj[V];
    addEdge(adj, 0, 1);
    addEdge(adj, 1, 2);
    addEdge(adj, 2, 0);
    addEdge(adj, 2, 3);
 
    if (isCyclicDisconntected(adj, V))
        cout << "Yes";
    else
        cout << "No";
 
    return 0;
}


Java
// Java program to detect cycle in
//  an undirected graph using BFS.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
 
class cycle
{
     
  public static void main(String arg[])
  {
 
    int V = 4;
    @SuppressWarnings("unchecked")
    ArrayList  adj[] = new ArrayList[V];
    for(int i = 0; i < 4; i++)
      adj[i] = new ArrayList();
 
    addEdge(adj, 0, 1);
    addEdge(adj, 1, 2);
    addEdge(adj, 2, 0);
    addEdge(adj, 2, 3);
 
    if (isCyclicDisconntected(adj, V))
      System.out.println("Yes");
    else
      System.out.println("No");
  }
 
  static void addEdge(ArrayList adj[], int u, int v)
  {
    adj[u].add(v);
    adj[v].add(u);
  }
 
  static boolean isCyclicConntected(
                             ArrayList adj[], int s,
                                    int V, boolean visited[])
  {
 
    // Set parent vertex for every vertex as -1.
    int parent[] = new int[V];
    Arrays.fill(parent, -1);
 
    // Create a queue for BFS
    Queue q = new LinkedList<>();
 
    // Mark the current node as
    // visited and enqueue it
    visited[s] = true;
    q.add(s);
 
    while (!q.isEmpty())
    {
 
      // Dequeue a vertex from
      // queue and print it
      int u = q.poll();
 
 
      // Get all adjacent vertices
      // of the dequeued vertex u.
      // If a adjacent has not been
      // visited, then mark it visited
      // and enqueue it. We also mark parent
      // so that parent is not considered
      // for cycle.
      for (int i = 0; i < adj[u].size(); i++)
      {
        int v = adj[u].get(i);
        if (!visited[v])
        {
          visited[v] = true;
          q.add(v);
          parent[v] = u;
        }
        else if (parent[u] != v)
          return true;
      }
    }
    return false;
  }
 
 
  static boolean isCyclicDisconntected(
                       ArrayList adj[], int V)
  {
 
    // Mark all the vertices as not visited
    boolean visited[] = new boolean[V];
    Arrays.fill(visited,false);
 
    for (int i = 0; i < V; i++)
      if (!visited[i] &&
          isCyclicConntected(adj, i, V, visited))
        return true;
    return false;
  }
}
 
// This code is contributed by mayukh Sengupta


Python3
# Python3 program to detect cycle in
# an undirected graph using BFS.
from collections import deque
 
def addEdge(adj: list, u, v):
    adj[u].append(v)
    adj[v].append(u)
 
def isCyclicConnected(adj: list, s, V,
                      visited: list):
 
    # Set parent vertex for every vertex as -1.
    parent = [-1] * V
 
    # Create a queue for BFS
    q = deque()
 
    # Mark the current node as
    # visited and enqueue it
    visited[s] = True
    q.append(s)
 
    while q != []:
 
        # Dequeue a vertex from queue and print it
        u = q.pop()
 
        # Get all adjacent vertices of the dequeued
        # vertex u. If a adjacent has not been visited,
        # then mark it visited and enqueue it. We also
        # mark parent so that parent is not considered
        # for cycle.
        for v in adj[u]:
            if not visited[v]:
                visited[v] = True
                q.append(v)
                parent[v] = u
            elif parent[u] != v:
                return True
 
    return False
 
def isCyclicDisconnected(adj: list, V):
 
    # Mark all the vertices as not visited
    visited = [False] * V
 
    for i in range(V):
        if not visited[i] and \
               isCyclicConnected(adj, i, V, visited):
            return True
    return False
 
# Driver Code
if __name__ == "__main__":
    V = 4
    adj = [[] for i in range(V)]
    addEdge(adj, 0, 1)
    addEdge(adj, 1, 2)
    addEdge(adj, 2, 0)
    addEdge(adj, 2, 3)
 
    if isCyclicDisconnected(adj, V):
        print("Yes")
    else:
        print("No")
 
# This code is contributed by
# sanjeev2552


C#
// A C# program to detect cycle in
// an undirected graph using BFS.
using System;
using System.Collections.Generic;
 
class GFG
{
    public static void Main(String []arg)
    {
        int V = 4;
        List []adj = new List[V];
        for (int i = 0; i < 4; i++)
        {
            adj[i] = new List();
        }
 
        addEdge(adj, 0, 1);
        addEdge(adj, 1, 2);
        addEdge(adj, 2, 0);
        addEdge(adj, 2, 3);
 
        if (isCyclicDisconntected(adj, V))
        {
            Console.WriteLine("Yes");
        }
        else
        {
            Console.WriteLine("No");
        }
    }
 
    static void addEdge(List []adj, int u, int v)
    {
        adj[u].Add(v);
        adj[v].Add(u);
    }
 
    static bool isCyclicConntected(List []adj, int s,
                                    int V, bool []visited)
    {
 
        // Set parent vertex for every vertex as -1.
        int []parent = new int[V];
        for (int i = 0; i < V; i++)
        parent[i] = -1;
 
        // Create a queue for BFS
        Queue q = new Queue();
 
        // Mark the current node as
        // visited and enqueue it
        visited[s] = true;
        q.Enqueue(s);
 
        while (q.Count != 0)
        {
 
            // Dequeue a vertex from
            // queue and print it
            int u = q.Dequeue();
 
            // Get all adjacent vertices
            // of the dequeued vertex u.
            // If a adjacent has not been
            // visited, then mark it visited
            // and enqueue it. We also mark parent
            // so that parent is not considered
            // for cycle.
            for (int i = 0; i < adj[u].Count; i++)
            {
                int v = adj[u][i];
                if (!visited[v])
                {
                    visited[v] = true;
                    q.Enqueue(v);
                    parent[v] = u;
                }
                else if (parent[u] != v)
                {
                    return true;
                }
            }
        }
        return false;
    }
 
    static bool isCyclicDisconntected(List []adj, int V)
    {
 
        // Mark all the vertices as not visited
        bool []visited = new bool[V];
 
        for (int i = 0; i < V; i++)
        {
            if (!visited[i] &&
                isCyclicConntected(adj, i, V, visited))
            {
                return true;
            }
        }
        return false;
    }
}
 
// This code is contributed by PrinciRaj1992


Javascript


输出:

Yes

时间复杂度:程序对图进行简单的 BFS 遍历,图使用邻接表表示。所以时间复杂度是O(V+E)