📌  相关文章
📜  查找无向图中两个顶点之间是否存在路径

📅  最后修改于: 2021-04-22 00:54:46             🧑  作者: Mango

给定一个无向图,该具有N个顶点和E个边,并且图中有两个顶点(U,V) ,任务是检测这两个顶点之间是否存在路径。打印“是”,如果存在路径和“否”,否则。

例子:

天真的方法:
这个想法是使用Floyd Warshall算法。为了解决该问题,我们需要尝试所有范围为[1,N]的中间顶点并检查:

  1. 如果两个节点之间已经存在直接边缘。
  2. 或者,我们具有从节点i到中间节点k以及从节点k到节点j的路径。

下面是上述方法的实现:

C++
// C++ program to detect if a path
// exists between any two vertices
// for the given undirected graph
#include 
using namespace std;
 
// Class representing a undirected
// graph using matrix
// representation
class Graph {
    int V;
    int** g;
 
public:
    Graph(int V);
 
    // Function to add an edge to graph
    void addEdge(int v, int w);
 
    // Function to check if
    // there exists a path or not
    bool isReachable(int s, int d);
 
    // function to compute paths
    // in the matrix using
    // Floyd Warshall Algorithm
    void computePaths();
};
 
Graph::Graph(int V)
{
    this->V = V;
    g = new int*[V + 1];
    for (int i = 1; i < V + 1; i++) {
        // Rows may not be contiguous
        g[i] = new int[V + 1];
 
        // Initialize all entries
        // as false to indicate
        // that there are
        // no edges initially
        memset(g[i], 0, (V + 1) * sizeof(int));
    }
 
    // Initializing node to itself
    // as it is always reachable
    for (int i = 1; i <= V; i++)
        g[i][i] = 1;
}
 
// Function to add edge between nodes
void Graph::addEdge(int v, int w)
{
    g[v][w] = 1;
    g[w][v] = 1;
}
 
// Function to compute the path
void Graph::computePaths()
{
    // Use Floyd Warshall algorithm
    // to detect if a path exists
    for (int k = 1; k <= V; k++) {
 
        // Try every vertex as an
        // intermediate vertex
        // to check if a path exists
        for (int i = 1; i <= V; i++) {
            for (int j = 1; j <= V; j++)
                g[i][j] = g[i][j]
                          | (g[i][k]
                             && g[k][j]);
        }
    }
}
 
// Function to check if nodes are reachable
bool Graph::isReachable(int s, int d)
{
 
    if (g[s][d] == 1)
        return true;
    else
        return false;
}
 
// Driver code
int main()
{
 
    Graph _g(4);
    _g.addEdge(1, 2);
    _g.addEdge(2, 3);
    _g.addEdge(1, 4);
    _g.computePaths();
 
    int u = 4, v = 3;
    if (_g.isReachable(u, v))
        cout << "Yes\n";
    else
        cout << "No\n";
 
    return 0;
}


Java
// Java program to detect if a path
// exists between any two vertices
// for the given undirected graph
import java.util.Arrays;
 
class GFG{
 
// Class representing a undirected
// graph using matrix representation
static class Graph
{
    int V;
    int[][] g;
 
    public Graph(int V)
    {
        this.V = V;
         
        // Rows may not be contiguous
        g = new int[V + 1][V + 1];
        for(int i = 0; i < V + 1; i++)
        {
             
            // Initialize all entries
            // as false to indicate
            // that there are
            // no edges initially
            Arrays.fill(g[i], 0);
        }
 
        // Initializing node to itself
        // as it is always reachable
        for(int i = 1; i <= V; i++)
            g[i][i] = 1;
    }
     
    // Function to add edge between nodes
    void addEdge(int v, int w)
    {
        g[v][w] = 1;
        g[w][v] = 1;
    }
 
    // Function to check if nodes are reachable
    boolean isReachable(int s, int d)
    {
        if (g[s][d] == 1)
            return true;
        else
            return false;
    }
     
    // Function to compute the path
    void computePaths()
    {
         
        // Use Floyd Warshall algorithm
        // to detect if a path exists
        for(int k = 1; k <= V; k++)
        {
             
            // Try every vertex as an
            // intermediate vertex
            // to check if a path exists
            for(int i = 1; i <= V; i++)
            {
                for(int j = 1; j <= V; j++)
                    g[i][j] = g[i][j] | ((g[i][k] != 0 &&
                              g[k][j] != 0) ? 1 : 0);
            }
        }
    }
};
 
// Driver code
public static void main(String[] args)
{
    Graph _g = new Graph(4);
    _g.addEdge(1, 2);
    _g.addEdge(2, 3);
    _g.addEdge(1, 4);
    _g.computePaths();
 
    int u = 4, v = 3;
    if (_g.isReachable(u, v))
        System.out.println("Yes");
    else
        System.out.println("No");
}
}
 
// This code is contributed by sanjeev2552


Python3
# Python3 program to detect if a path
# exists between any two vertices
# for the given undirected graph
 
# Class representing a undirected
# graph using matrix
# representation
class Graph:
     
    def __init__(self, V):
         
        self.V = V
         
        # Initialize all entries
        # as false to indicate
        # that there are
        # no edges initially
        self.g = [[0 for j in range(self.V + 1)]
                     for i in range(self.V + 1)]
     
        # Initializing node to itself
        # as it is always reachable
        for i in range(self.V + 1):
            self.g[i][i] = 1
 
    # Function to add edge between nodes
    def addEdge(self, v, w):
 
        self.g[v][w] = 1
        self.g[w][v] = 1
 
    # Function to compute the path
    def computePaths(self):
 
        # Use Floyd Warshall algorithm
        # to detect if a path exists
        for k in range(1, self.V + 1):
 
            # Try every vertex as an
            # intermediate vertex
            # to check if a path exists
            for i in range(1, self.V + 1):
                for j in range(1, self.V + 1):
                    self.g[i][j] = (self.g[i][j] |
                                   (self.g[i][k] and
                                    self.g[k][j]))
                     
    # Function to check if nodes
    # are reachable
    def isReachable(self, s, d):
 
        if (self.g[s][d] == 1):
            return True
        else:
            return False
           
# Driver code
if __name__=='__main__':
 
    _g = Graph(4)
    _g.addEdge(1, 2)
    _g.addEdge(2, 3)
    _g.addEdge(1, 4)
    _g.computePaths()
 
    u = 4
    v = 3
     
    if (_g.isReachable(u, v)):
        print('Yes')
    else:
        print('No')
         
# This code is contributed by rutvik_56


C++
// C++ program to check if there is exist a path between
// two vertices of an undirected graph.
#include 
#include 
using namespace std;
 
// This class represents an undirected graph
// using adjacency list representation
class Graph {
    int V; // No. of vertices
 
    // Pointer to an array containing adjacency lists
    list* adj;
public:
    Graph(int V); // Constructor
 
    // function to add an edge to graph
    void addEdge(int v, int w);
    bool isReachable(int s, int d);
};
 
Graph::Graph(int V)
{
    this->V = V;
    adj = new list[V];
}
 
void Graph::addEdge(int v, int w)
{
    adj[v].push_back(w);
    adj[w].push_back(v);
}
 
// A BFS based function to check whether d is reachable from s.
bool Graph::isReachable(int s, int d)
{
    // Base case
    if (s == d)
        return true;
 
    // Mark all the vertices as not visited
    bool* visited = new bool[V];
    for (int i = 0; i < V; i++)
        visited[i] = false;
 
    // Create a queue for BFS
    list queue;
 
    // Mark the current node as visited and enqueue it
    visited[s] = true;
    queue.push_back(s);
 
    // it will be used to get all adjacent vertices of a vertex
    list::iterator i;
 
    while (!queue.empty()) {
        // Dequeue a vertex from queue and print it
        s = queue.front();
        queue.pop_front();
 
        // Get all adjacent vertices of the dequeued vertex s
        // If a adjacent has not been visited, then mark it
        // visited  and enqueue it
        for (i = adj[s].begin(); i != adj[s].end(); ++i) {
 
            // If this adjacent node is the destination node,
            // then return true
            if (*i == d)
                return true;
 
            // Else, continue to do BFS
            if (!visited[*i]) {
                visited[*i] = true;
                queue.push_back(*i);
            }
        }
    }
 
    // If BFS is complete without visiting d
    return false;
}
 
// Driver program to test methods of graph class
int main()
{
    // Create a graph given in the above diagram
    Graph g(4);
    g.addEdge(0, 1);
    g.addEdge(0, 2);
    g.addEdge(1, 2);
    g.addEdge(2, 0);
    g.addEdge(2, 3);
    g.addEdge(3, 3);
 
    int u = 1, v = 3;
    if (g.isReachable(u, v))
        cout << "\n There is a path from " << u << " to " << v;
    else
        cout << "\n There is no path from " << u << " to " << v;
 
    return 0;
}


Python3
# Python3 program to check if there is exist a path between
# two vertices of an undirected graph.
from collections import deque
def addEdge(v, w):
    global adj
    adj[v].append(w)
    adj[w].append(v)
 
# A BFS based function to check whether d is reachable from s.
def isReachable(s, d):
     
    # Base case
    if (s == d):
        return True
 
    # Mark all the vertices as not visited
    visited = [False for i in range(V)]
 
    # Create a queue for BFS
    queue = deque()
 
    # Mark the current node as visited and enqueue it
    visited[s] = True
    queue.append(s)
 
    while (len(queue) > 0):
       
        # Dequeue a vertex from queue and prit
        s = queue.popleft()
        # queue.pop_front()
 
        # Get all adjacent vertices of the dequeued vertex s
        # If a adjacent has not been visited, then mark it
        # visited  and enqueue it
        for i in adj[s]:
 
            # If this adjacent node is the destination node,
            # then return true
            if (i == d):
                return True
 
            # Else, continue to do BFS
            if (not visited[i]):
                visited[i] = True
                queue.append(i)
    # If BFS is complete without visiting d
    return False
 
# Driver program to test methods of graph class
if __name__ == '__main__':
   
    # Create a graph given in the above diagram
    V = 4
    adj = [[] for i in range(V+1)]
    addEdge(0, 1)
    addEdge(0, 2)
    addEdge(1, 2)
    addEdge(2, 0)
    addEdge(2, 3)
    addEdge(3, 3)
    u,v = 1, 3
    if (isReachable(u, v)):
        print("There is a path from",u,"to",v)
    else:
        print("There is no path from",u,"to",v)
 
        # This code is contributed by mohit kumar 29.


输出:
Yes

时间复杂度: O(V 3 )
辅助空间: O(V 2 )

高效的解决方案
我们可以使用BFS或DFS查找是否存在从u到v的路径。以下是基于BFS的解决方案

C++

// C++ program to check if there is exist a path between
// two vertices of an undirected graph.
#include 
#include 
using namespace std;
 
// This class represents an undirected graph
// using adjacency list representation
class Graph {
    int V; // No. of vertices
 
    // Pointer to an array containing adjacency lists
    list* adj;
public:
    Graph(int V); // Constructor
 
    // function to add an edge to graph
    void addEdge(int v, int w);
    bool isReachable(int s, int d);
};
 
Graph::Graph(int V)
{
    this->V = V;
    adj = new list[V];
}
 
void Graph::addEdge(int v, int w)
{
    adj[v].push_back(w);
    adj[w].push_back(v);
}
 
// A BFS based function to check whether d is reachable from s.
bool Graph::isReachable(int s, int d)
{
    // Base case
    if (s == d)
        return true;
 
    // Mark all the vertices as not visited
    bool* visited = new bool[V];
    for (int i = 0; i < V; i++)
        visited[i] = false;
 
    // Create a queue for BFS
    list queue;
 
    // Mark the current node as visited and enqueue it
    visited[s] = true;
    queue.push_back(s);
 
    // it will be used to get all adjacent vertices of a vertex
    list::iterator i;
 
    while (!queue.empty()) {
        // Dequeue a vertex from queue and print it
        s = queue.front();
        queue.pop_front();
 
        // Get all adjacent vertices of the dequeued vertex s
        // If a adjacent has not been visited, then mark it
        // visited  and enqueue it
        for (i = adj[s].begin(); i != adj[s].end(); ++i) {
 
            // If this adjacent node is the destination node,
            // then return true
            if (*i == d)
                return true;
 
            // Else, continue to do BFS
            if (!visited[*i]) {
                visited[*i] = true;
                queue.push_back(*i);
            }
        }
    }
 
    // If BFS is complete without visiting d
    return false;
}
 
// Driver program to test methods of graph class
int main()
{
    // Create a graph given in the above diagram
    Graph g(4);
    g.addEdge(0, 1);
    g.addEdge(0, 2);
    g.addEdge(1, 2);
    g.addEdge(2, 0);
    g.addEdge(2, 3);
    g.addEdge(3, 3);
 
    int u = 1, v = 3;
    if (g.isReachable(u, v))
        cout << "\n There is a path from " << u << " to " << v;
    else
        cout << "\n There is no path from " << u << " to " << v;
 
    return 0;
}

Python3

# Python3 program to check if there is exist a path between
# two vertices of an undirected graph.
from collections import deque
def addEdge(v, w):
    global adj
    adj[v].append(w)
    adj[w].append(v)
 
# A BFS based function to check whether d is reachable from s.
def isReachable(s, d):
     
    # Base case
    if (s == d):
        return True
 
    # Mark all the vertices as not visited
    visited = [False for i in range(V)]
 
    # Create a queue for BFS
    queue = deque()
 
    # Mark the current node as visited and enqueue it
    visited[s] = True
    queue.append(s)
 
    while (len(queue) > 0):
       
        # Dequeue a vertex from queue and prit
        s = queue.popleft()
        # queue.pop_front()
 
        # Get all adjacent vertices of the dequeued vertex s
        # If a adjacent has not been visited, then mark it
        # visited  and enqueue it
        for i in adj[s]:
 
            # If this adjacent node is the destination node,
            # then return true
            if (i == d):
                return True
 
            # Else, continue to do BFS
            if (not visited[i]):
                visited[i] = True
                queue.append(i)
    # If BFS is complete without visiting d
    return False
 
# Driver program to test methods of graph class
if __name__ == '__main__':
   
    # Create a graph given in the above diagram
    V = 4
    adj = [[] for i in range(V+1)]
    addEdge(0, 1)
    addEdge(0, 2)
    addEdge(1, 2)
    addEdge(2, 0)
    addEdge(2, 3)
    addEdge(3, 3)
    u,v = 1, 3
    if (isReachable(u, v)):
        print("There is a path from",u,"to",v)
    else:
        print("There is no path from",u,"to",v)
 
        # This code is contributed by mohit kumar 29.
输出:
There is a path from 1 to 3

时间复杂度: O(V + E)
辅助空间: O(V)