检查我们是否能从给定的定向图中的任何节点访问所有其他节点
给定N个节点,其中每个节点的编号从0到N-1, 以及数组边, 其中有一条从edges[i][0]到edges[i][1] 的有向边**,** 任务是找出我们是否能从任何节点到所有其他节点。
例子。
输入。 N = 2, edges[] = {{0, 1}, {1, 0}};
输出。 真
解释。 我们可以从1去到节点0,从0去到节点1。**输入。**N = 3, edges[] = {{1, 0}};
**输出。**错
建议的做法
一个使用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)