📌  相关文章
📜  从给定集中存在的每个节点中查找所有可达节点

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

从给定集中存在的每个节点中查找所有可达节点

给定一个无向图和一组顶点,从给定集合中存在的每个顶点中找到所有可到达的节点。

考虑下面的无向图,其中包含 2 个断开的组件。

GraphEx1

arr[] = {1 , 2 , 5}
Reachable nodes from 1 are  1, 2, 3, 4
Reachable nodes from 2 are 1, 2, 3, 4
Reachable nodes from 5 are 5, 6, 7

方法1(简单)

一种直接的解决方案是对集合中存在的每个节点进行 BFS 遍历,然后找到所有可到达的节点。
假设我们需要找到 n 个节点的可达节点,该解决方案的时间复杂度为 O(n*(V+E)),其中 V 是图中的节点数,E 是图中的边数。请注意,我们需要调用 BFS 作为每个节点的单独调用,而不使用先前遍历的已访问数组,因为可能需要多次打印相同的顶点。这似乎是一个有效的解决方案,但考虑当 E = Θ(V 2 ) 和 n = V 的情况,时间复杂度变为 O(V 3 )。

方法二(高效)

由于给定的图是无向的,属于同一组件的所有顶点都具有相同的可达节点集。所以我们跟踪顶点和组件映射。图中的每个组件都分配了一个编号,并且该组件中的每个顶点都分配了这个编号。为此,我们使用访问数组,该数组用于跟踪 BFS 中访问的顶点。

For a node u, 
if visit[u] is 0 then
    u has not been visited before
else // if not zero then
   visit[u] represents the component number. 

For any two nodes u and v belonging to same 
component, visit[u] is equal to visit[v]

要存储可达节点,请使用映射m ,其中键作为组件编号,值作为存储所有可达节点的向量。

要找到节点的可达节点u返回m[visit[u]]
查看下面的伪代码以了解如何分配组件编号。

componentNum = 0
for i=1 to n    
    If visit[i] is NOT 0 then
        componentNum++ 
         
        // bfs() returns a list (or vector)
        // for given vertex 'i'
        list = bfs(i, componentNum)
        m[visit[i]]] = list

对于示例中显示的图表,访问数组将是。

访问数组 (2)

对于节点 1、2、3 和 4,组件编号为 1。对于节点 5、6 和 7,组件编号为 2。

上述想法的实现

C++
// C++ program to find all the reachable nodes
// for every node present in arr[0..n-1].
#include 
using namespace std;
 
// This class represents a directed graph using
// adjacency list representation
class Graph
{
public:
    int V;    // No. of vertices
 
    // Pointer to an array containing adjacency lists
    list *adj;
 
    Graph(int );  // Constructor
 
    void addEdge(int, int);
 
    vector BFS(int, int, int []);
};
 
Graph::Graph(int V)
{
    this->V = V;
    adj = new list[V+1];
}
 
void Graph::addEdge(int u, int v)
{
    adj[u].push_back(v); // Add w to v’s list.
    adj[v].push_back(u); // Add v to w’s list.
}
 
vector Graph::BFS(int componentNum, int src,
                                    int visited[])
{
    // Mark all the vertices as not visited
    // Create a queue for BFS
    queue queue;
 
    queue.push(src);
 
    // Assign Component Number
    visited[src] = componentNum;
 
    // Vector to store all the reachable nodes from 'src'
    vector reachableNodes;
 
    while(!queue.empty())
    {
        // Dequeue a vertex from queue
        int u = queue.front();
        queue.pop();
 
        reachableNodes.push_back(u);
 
        // Get all adjacent vertices of the dequeued
        // vertex u. If a adjacent has not been visited,
        // then mark it visited nd enqueue it
        for (auto itr = adj[u].begin();
                itr != adj[u].end(); itr++)
        {
            if (!visited[*itr])
            {
                // Assign Component Number to all the
                // reachable nodes
                visited[*itr] = componentNum;
                queue.push(*itr);
            }
        }
    }
    return reachableNodes;
}
 
// Display all the Reachable Nodes from a node 'n'
void displayReachableNodes(int n,
            unordered_map  > m)
{
    vector temp = m[n];
    for (int i=0; i > m;
 
    // Initialize component Number with 0
    int componentNum = 0;
 
    // For each node in arr[] find reachable
    // Nodes
    for (int i = 0 ; i < n ; i++)
    {
        int u = arr[i];
 
        // Visit all the nodes of the component
        if (!visited[u])
        {
            componentNum++;
 
            // Store the reachable Nodes corresponding to
            // the node 'i'
            m[visited[u]] = g.BFS(componentNum, u, visited);
        }
 
        // At this point, we have all reachable nodes
        // from u, print them by doing a look up in map m.
        cout << "Reachable Nodes from " << u <<" are\n";
        displayReachableNodes(visited[u], m);
    }
}
 
// Driver program to test above functions
int main()
{
    // Create a graph given in the above diagram
    int V = 7;
    Graph g(V);
    g.addEdge(1, 2);
    g.addEdge(2, 3);
    g.addEdge(3, 4);
    g.addEdge(3, 1);
    g.addEdge(5, 6);
    g.addEdge(5, 7);
 
    // For every ith element in the arr
    // find all reachable nodes from query[i]
    int arr[] = {2, 4, 5};
 
    // Find number of elements in Set
    int n = sizeof(arr)/sizeof(int);
 
    findReachableNodes(g, arr, n);
 
    return 0;
}


Python3
# Python3 program to find all the reachable nodes
# for every node present in arr[0..n-1]
from collections import deque
 
def addEdge(v, w):
     
    global visited, adj
    adj[v].append(w)
    adj[w].append(v)
 
def BFS(componentNum, src):
     
    global visited, adj
     
    # Mark all the vertices as not visited
    # Create a queue for BFS
    #a =  visited
    queue = deque()
 
    queue.append(src)
 
    # Assign Component Number
    visited[src] = 1
 
    # Vector to store all the reachable
    # nodes from 'src'
    reachableNodes = []
    #print("0:",visited)
 
    while (len(queue) > 0):
         
        # Dequeue a vertex from queue
        u = queue.popleft()
 
        reachableNodes.append(u)
 
        # Get all adjacent vertices of the dequeued
        # vertex u. If a adjacent has not been visited,
        # then mark it visited nd enqueue it
        for itr in adj[u]:
            if (visited[itr] == 0):
                 
                # Assign Component Number to all the
                # reachable nodes
                visited[itr] = 1
                queue.append(itr)
 
    return reachableNodes
 
# Display all the Reachable Nodes
# from a node 'n'
def displayReachableNodes(m):
     
    for i in m:
        print(i, end = " ")
 
    print()
 
def findReachableNodes(arr, n):
     
    global V, adj, visited
     
    # Get the number of nodes in the graph
 
    # Map to store list of reachable Nodes for a
    # given node.
    a = []
 
    # Initialize component Number with 0
    componentNum = 0
 
    # For each node in arr[] find reachable
    # Nodes
    for i in range(n):
        u = arr[i]
 
        # Visit all the nodes of the component
        if (visited[u] == 0):
            componentNum += 1
 
            # Store the reachable Nodes corresponding
            # to the node 'i'
            a = BFS(componentNum, u)
 
        # At this point, we have all reachable nodes
        # from u, print them by doing a look up in map m.
        print("Reachable Nodes from ", u, " are")
        displayReachableNodes(a)
 
# Driver code
if __name__ == '__main__':
     
    V = 7
    adj = [[] for i in range(V + 1)]
    visited = [0 for i in range(V + 1)]
    addEdge(1, 2)
    addEdge(2, 3)
    addEdge(3, 4)
    addEdge(3, 1)
    addEdge(5, 6)
    addEdge(5, 7)
 
    # For every ith element in the arr
    # find all reachable nodes from query[i]
    arr = [ 2, 4, 5 ]
 
    # Find number of elements in Set
    n = len(arr)
 
    findReachableNodes(arr, n)
 
# This code is contributed by mohit kumar 29


输出:

Reachable Nodes from 2 are
2 1 3 4 
Reachable Nodes from 4 are
2 1 3 4 
Reachable Nodes from 5 are
5 6 7

时间复杂度分析:
n = 给定集合的大小
E = 边数
V = 节点数
BFS 的 O(V+E)
在最坏的情况下,为给定中存在的每个节点显示所有 V 节点,即图中只有一个组件,因此需要 O(n*V) 时间。
最坏情况时间复杂度:O(V+E) + O(n*V)