检查是否能从给定的定向图中的任何一个节点访问所有其他节点

145 阅读3分钟

检查我们是否能从给定的定向图中的任何节点访问所有其他节点

给定N个节点,其中每个节点的编号从0N-1, 以及数组边, 其中有一条从edges[i][0]edges[i][1] 的有向边**,** 任务是找出我们是否能从任何节点到所有其他节点。

例子。

输入。 N = 2, edges[] = {{0, 1}, {1, 0}};
输出。
解释。 我们可以从1去到节点0,从0去到节点1。

**输入。**N = 3, edges[] = {{1, 0}};
**输出。**错

建议的做法

请先在IDE上尝试你的方法,然后再
,继续解决问题。

试试吧!

一个使用Kosaraju算法的方法。

解决这个问题的一个思路是,从寻找有向图的强连接部分 (SCC) 的角度来考虑,我们知道,如果所有的顶点对之间都有一条路径,那么有向图就是强连接的。

因此,如果只有一个SCC,那么我们只能从任何其他节点访问所有的节点。使用Kosaraju的算法可以找到SCC的数量。

按照下面的步骤来实现上述想法。

  • 创建邻接列表adj1 来存储图。
  • 做到 DFS按照顶点的随机顺序,将访问过的顶点存储在堆栈 stk中,同时进行回溯。
  • adj1 图的所有边的方向反转,将新创建的图存储在adj2中。
  • 按照堆栈的顺序做DFS2 ,并在变量scc中保留强连接部分的计数。
  • 检查scc的计数。
    • 如果scc 的计数大于1,返回false。
    • 否则,返回true。

下面是上述方法的实现。

C++

// C++ code to implement above approach

#include <bits/stdc++.h>
using namespace std;

// Function to find components
void randomOrderDfs(int i, vector<vector<int> >& adj,
                    vector<bool>& visited, stack<int>& stk)
{
    visited[i] = true;

    for (auto child : adj[i]) {
        if (visited[child] == false) {
            randomOrderDfs(child, adj, visited, stk);
        }
    }

    stk.push(i);
}

// Function to traverse in the reversed graph
void dfs2(int i, vector<vector<int> >& adj,
          vector<bool>& visited)
{
    visited[i] = true;

    for (auto child : adj[i]) {
        if (visited[child] == false) {
            dfs2(child, adj, visited);
        }
    }
}

// Function to check if it is possible
// to reach all other nodes from any node
bool isTourPossible(int n, vector<vector<int> >& roads)
{
    // adj1 stores adjacency matrix of
    // original graph adj2 stores
    // adjacency matrix of original graph
    // by reversing direction of all edges
    vector<vector<int> > adj1(n), adj2(n);

    // Create graph
    for (auto i : roads) {
        adj1[i[0]].push_back(i[1]);
    }

    vector<bool> visited1(n, false), visited2(n, false);
    stack<int> stk;

    // Random dfs and maintain stack
    // at backtracking (endpoint)
    for (int i = 0; i < n; i++) {
        if (visited1[i] == false) {
            randomOrderDfs(i, adj1, visited1, stk);
        }
    }

    // Reverse all the edges
    for (int i = 0; i < n; i++) {
        for (auto child : adj1[i]) {
            adj2[child].push_back(i);
        }
    }

    // scc for counting the number of
    // strongly connected component
    int scc = 0;

    // Make second dfs at order of stk
    while (stk.size() > 0) {
        int node = stk.top();
        if (visited2[node]) {
            stk.pop();
        }
        else {
            dfs2(node, adj2, visited2);
            stk.pop();
            scc++;

            if (scc > 1)
                return false;
        }
    }

    return true;
}

// Driver code
int main()
{
    int N = 2;
    vector<vector<int> > edges = { { 0, 1 }, { 1, 0 } };

    // Function call
    bool result = isTourPossible(N, edges);

    if (result) {
        cout << "True" << endl;
    }
    else {
        cout << "False" << endl;
    }
    return 0;
}

JAVA

// Java program to implement the approach
import java.io.*;
import java.util.*;

// Function to find components
class GFG
{
  
    // Function to find components
    static void
    randomOrderDfs(int i,
                   ArrayList<ArrayList<Integer> > adj,
                   boolean[] visited, Stack<Integer> stk)
    {
        visited[i] = true;

        for (int j = 0; j < adj.get(i).size(); j++) {
            int child = adj.get(i).get(j);
            if (visited[child] == false) {
                randomOrderDfs(child, adj, visited, stk);
            }
        }

        stk.push(i);
    }

    // Function to traverse in the reversed graph
    static void dfs2(int i,
                     ArrayList<ArrayList<Integer> > adj,
                     boolean[] visited)
    {
        visited[i] = true;

        for (int j = 0; j < adj.get(i).size(); j++) {
            int child = adj.get(j).get(0);
            if (visited[child] == false) {
                dfs2(child, adj, visited);
            }
        }
    }

    // Function to check if it is possible
    // to reach all other nodes from any node
    static boolean isTourPossible(int n, int[][] roads)
    {
        // adj1 stores adjacency matrix of
        // original graph adj2 stores
        // adjacency matrix of original graph
        // by reversing direction of all edges
        ArrayList<ArrayList<Integer> > adj1
            = new ArrayList<>();
        ArrayList<ArrayList<Integer> > adj2
            = new ArrayList<>();
        ;
        for (int i = 0; i < n; i++) {
            adj1.add(new ArrayList<Integer>());
            adj2.add(new ArrayList<Integer>());
        }

        // Create graph
        for (int i = 0; i < n; i++) {
            adj1.get(roads[i][0]).add(roads[i][1]);
        }

        boolean[] visited1 = new boolean[n];
        boolean[] visited2 = new boolean[n];
        for (int i = 0; i < n; i++) {
            visited1[i] = false;
            visited2[i] = false;
        }
        Stack<Integer> stk = new Stack<Integer>();

        // Random dfs and maintain stack
        // at backtracking (endpoint)
        for (int i = 0; i < n; i++) {
            if (visited1[i] == false) {
                randomOrderDfs(i, adj1, visited1, stk);
            }
        }

        // Reverse all the edges
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < adj1.get(i).size(); j++) {
                int child = adj1.get(i).get(j);
                adj2.get(child).add(i);
            }
        }

        // scc for counting the number of
        // strongly connected component
        int scc = 0;

        // Make second dfs at order of stk
        while (stk.size() > 0) {
            int node = stk.peek();
            if (visited2[node]) {
                stk.pop();
            }
            else {
                dfs2(node, adj2, visited2);
                stk.pop();
                scc++;

                if (scc > 1)
                    return false;
            }
        }

        return true;
    }

    // Driver code
    public static void main(String[] args)
    {
        int N = 2;
        int edges[][] = { { 0, 1 }, { 1, 0 } };

        // Function call
        boolean result = isTourPossible(N, edges);

        if (result) {
            System.out.println("True");
        }
        else {
            System.out.println("False");
        }
    }
}

// This code is contributed by garg28harsh.

Python3

# Python code to implement above approach

# Function to find components
def randomOrderDfs(i, adj, visited, stk):
    visited[i] = True
    for child in adj[i]:
        if(visited[child] == False):
            randomOrderDfs(child, adj, visited, stk)
    stk.append(i)

# Function to traverse in the reversed graph
def dfs2(i, adj, visited):
    visited[i] = True
    
    for child in adj[i]:
        if(visited[child] == False):
            dfs2(child, adj, visited)
    
# Function to check if it is possible
# to reach all other nodes from any node
def isTourPossible(n,roads):
    # adj1 stores adjacency matrix of
    # original graph adj2 stores
    # adjacency matrix of original graph
    # by reversing direction of all edges
    adj1 = [[] for i in range(n)]
    adj2 = [[] for i in range(n)]
    
    # Create graph
    for i in roads:
        adj1[i[0]].append(i[1])
    
    visited1 = [False]*n
    visited2 = [False]*n
    stk = []
    
    # Random dfs and maintain stack
    # at backtracking (endpoint)
    for i in range(n):
        if(visited1[i]==False):
            randomOrderDfs(i,adj1,visited1,stk)
    
    # Reverse all the edges
    for i in range(n):
        for child in adj1[i]:
            adj2[child].append(i)
    
    # scc for counting the number of
    # strongly connected component
    scc=0
    
    # Make second dfs at order of stk
    while(len(stk) > 0):
        node = stk[len(stk)-1]
        if(visited2[node]):
            stk.pop()
        else:
            dfs2(node,adj2,visited2)
            stk.pop()
            scc = scc + 1
            
            if(scc>1):
                return False
                
    return True

# Driver code
N = 2
edges = [[0,1],[1,0]]

# Function call
result = isTourPossible(N,edges)
if(result):
    print("True")
else:
    print("False")
    
# This code is contributed by Pushpesh Raj.

输出

True

**时间复杂度。**O(N+E),其中E是边的数量
**辅助空间。**O(N+E)