📌  相关文章
📜  访问给定图的所有节点的最小顶点集

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

访问给定图的所有节点的最小顶点集

给定一个有 N 个节点的有向无环图,任务是找到可以访问完整图的最小顶点集。

例子:

方法 1:给定问题可以使用拓扑排序来解决,以获得顶点的排序,使得对于从UV的每条有向边, U都在V之前。以下是要遵循的步骤:

  • 使用 Khan 算法按拓扑顺序对给定的顶点数组进行排序。
  • 维护一个访问过的数组,该数组跟踪访问过的顶点。
  • 迭代排序后的数组执行以下操作:
    • 如果当前顶点未被访问,则将其插入所需的集合中。
    • 使用 DFS 遍历访问从插入节点可到达的所有节点。

下面是上述方法的实现:

Python3
# Python program of the above approach
from collections import defaultdict, deque
 
class Solution:
 
      # Function to perform DFS
    def dfs(self, node, vis, graph):
 
        # add node to visited set
        vis.add(node)
 
        for adj in graph[node]:
            if (adj not in vis):
                self.dfs(adj, vis, graph)
 
    def solve(self, edges):
 
        graph = defaultdict(list)
 
        # dictionary storing
        # indegrees of node
        indeg = defaultdict(int)
 
        # array to store topological
        # sorting of the array
        topo_sort = []
        vis = set()
 
        for (u, v) in edges:
            graph[u].append(v)
 
            # count indegree of each node
            indeg[v] += 1
 
        qu = deque()
 
        for u in graph:
 
            # add to ququ ,if indegree
            # of node u is 0
            if(indeg[u] == 0):
                qu.append(u)
 
        # Run till queue is not empty
        while(qu):
 
            node = qu.popleft()
 
            # add node to topo_sort
            topo_sort.append(node)
 
            # traverse adj nodes
            for adj in graph[node]:
 
                # decrement count of indegree
                # of each adj node by 1
                indeg[adj] -= 1
 
                # if count becomes 0, then
                # add adj to qu
                if (indeg[adj] == 0):
                    qu.append(adj)
 
        vis = set()
        ans = []
 
        # Take each node from topo_sort
        for node in topo_sort:
 
            # check if node is visited
            if (node not in vis):
 
                vis.add(node)
                ans.append(node)
 
                # Mark all the reachable
                # nodes as visited
                self.dfs(node, vis, graph)
 
        # finally return ans
        return (ans)
 
 
obj = Solution()
edges = [[0, 1], [2, 1], [3, 2], [4, 3]]
 
ans = obj.solve(edges)
print(" ".join(str(n) for n in ans))


C++
// C++ program of the above approach
#include 
using namespace std;
 
// Function to find smallest set
// of vertices from which the
// complete graph can be visited
vector solve(vector>& edges)
{
    map graph;
 
    // Dictionary storing
    // indgree of nodes
    map indeg;
 
    for(auto dt : edges)
    {
        graph[dt[0]] = dt[1];
         
        // Count indegree of
        // each node
        indeg[dt[1]] += 1;
    }
 
    vector ans;
    for(auto it = graph.begin();
             it != graph.end(); ++it)
    {
         
        // Add to ans, if indegree
        // of node u is 0
        if (!indeg.count(it->first))
            ans.push_back(it->first);
    }
 
    // Return Ans
    return ans;
}
 
// Driver code
int main()
{
    vector> edges = { { 0, 1 }, { 2, 1 },
                                  { 3, 2 }, { 4, 3 } };
 
    vector ans = solve(edges);
    for(auto dt : ans)
        cout << dt << " ";
 
    return 0;
}
 
// This code is contributed by rakeshsahni


Java
// Java program of the above approach
import java.util.*;
 
class GFG{
 
// Function to find smallest set
// of vertices from which the
// complete graph can be visited
static Vector solve(int[][] edges)
{
    HashMap graph = new HashMap();
 
    // Dictionary storing
    // indgree of nodes
    HashMap indeg = new HashMap();
 
    for(int dt[] : edges)
    {
        graph.put(dt[0], dt[1]);
         
        // Count indegree of
        // each node
        if(indeg.containsKey(dt[1])) {
            indeg.put(dt[1], indeg.get(dt[1])+1);
        }
        else
            indeg.put(dt[1], 1);
    }
 
    Vector ans = new Vector();
    for (Map.Entry it : graph.entrySet())
    {
         
        // Add to ans, if indegree
        // of node u is 0
        if (!indeg.containsKey(it.getKey()))
            ans.add(it.getKey());
    }
 
    // Return Ans
    return ans;
}
 
// Driver code
public static void main(String[] args)
{
    int[][]edges = { { 0, 1 }, { 2, 1 },
                                  { 3, 2 }, { 4, 3 } };
 
    Vector ans = solve(edges);
    for(int dt : ans)
        System.out.print(dt+ " ");
 
}
}
 
// This code is contributed by shikhasingrajput


Python3
# Python program of the above approach
from collections import defaultdict
 
class Solution:
     
    # Function to find smallest set
    # of vertices from which the
    # complete graph can be visited
    def solve(self , edges):
 
        graph = defaultdict(list)
 
        # dictionary storing
        # indgree of nodes
        indeg = defaultdict(int)
 
        for (u,v) in edges:
            graph[u].append(v)
 
            # count indegree of
            # each node
            indeg[v] +=1
 
        ans = []
        for u in graph:
             
            # add to ans, if indegree
            # of node u is 0
            if(indeg[u] == 0):
                ans.append(u)
 
        # Return Ans
        return (ans)
             
 
obj = Solution()
edges = [[0,1] , [2,1] , [3,2] , [4,3] ]
 
ans= obj.solve(edges)
print(" ".join(str(n) for n in ans))


C#
// C# program of the above approach
using System;
using System.Collections.Generic;
 
public class GFG {
 
    // Function to find smallest set
    // of vertices from which the
    // complete graph can be visited
    static List solve(int[, ] edges)
    {
        Dictionary graph
            = new Dictionary();
 
        // Dictionary storing
        // indgree of nodes
        Dictionary indeg
            = new Dictionary();
        for (int k = 0; k < edges.GetLength(0); k++) {
            int keys = edges[k, 0];
            int values = edges[k, 1];
            graph.Add(keys, values);
 
            // Count indegree of
            // each node
            if (indeg.ContainsKey(values)) {
                indeg[values] += 1;
            }
            else
                indeg.Add(values, 1);
        }
 
        List ans = new List();
        foreach(KeyValuePair it in graph)
        {
 
            // Add to ans, if indegree
            // of node u is 0
            if (!indeg.ContainsKey(it.Key))
                ans.Add(it.Key);
        }
 
        // Return Ans
        return ans;
    }
    public static int[] GetRow(int[, ] matrix, int row)
    {
        var rowLength = matrix.GetLength(1);
        var rowVector = new int[rowLength];
 
        for (var i = 0; i < rowLength; i++)
            rowVector[i] = matrix[row, i];
 
        return rowVector;
    }
   
    // Driver code
    public static void Main(String[] args)
    {
        int[, ] edges
            = { { 0, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 } };
 
        List ans = solve(edges);
        foreach(int dt in ans) Console.Write(dt + " ");
    }
}
 
// This code is contributed by 29AjayKumar


输出
0 4

时间复杂度: O(N)
辅助空间: O(N)

方法2:给定问题也可以通过观察度数为0的顶点是任何其他顶点都无法到达的顶点来解决。因此,我们的想法是找到每个顶点的入度,并将入度为0的顶点插入所需的集合中,因为最终可以访问所有其他顶点。

下面是上述方法的实现:

C++

// C++ program of the above approach
#include 
using namespace std;
 
// Function to find smallest set
// of vertices from which the
// complete graph can be visited
vector solve(vector>& edges)
{
    map graph;
 
    // Dictionary storing
    // indgree of nodes
    map indeg;
 
    for(auto dt : edges)
    {
        graph[dt[0]] = dt[1];
         
        // Count indegree of
        // each node
        indeg[dt[1]] += 1;
    }
 
    vector ans;
    for(auto it = graph.begin();
             it != graph.end(); ++it)
    {
         
        // Add to ans, if indegree
        // of node u is 0
        if (!indeg.count(it->first))
            ans.push_back(it->first);
    }
 
    // Return Ans
    return ans;
}
 
// Driver code
int main()
{
    vector> edges = { { 0, 1 }, { 2, 1 },
                                  { 3, 2 }, { 4, 3 } };
 
    vector ans = solve(edges);
    for(auto dt : ans)
        cout << dt << " ";
 
    return 0;
}
 
// This code is contributed by rakeshsahni

Java

// Java program of the above approach
import java.util.*;
 
class GFG{
 
// Function to find smallest set
// of vertices from which the
// complete graph can be visited
static Vector solve(int[][] edges)
{
    HashMap graph = new HashMap();
 
    // Dictionary storing
    // indgree of nodes
    HashMap indeg = new HashMap();
 
    for(int dt[] : edges)
    {
        graph.put(dt[0], dt[1]);
         
        // Count indegree of
        // each node
        if(indeg.containsKey(dt[1])) {
            indeg.put(dt[1], indeg.get(dt[1])+1);
        }
        else
            indeg.put(dt[1], 1);
    }
 
    Vector ans = new Vector();
    for (Map.Entry it : graph.entrySet())
    {
         
        // Add to ans, if indegree
        // of node u is 0
        if (!indeg.containsKey(it.getKey()))
            ans.add(it.getKey());
    }
 
    // Return Ans
    return ans;
}
 
// Driver code
public static void main(String[] args)
{
    int[][]edges = { { 0, 1 }, { 2, 1 },
                                  { 3, 2 }, { 4, 3 } };
 
    Vector ans = solve(edges);
    for(int dt : ans)
        System.out.print(dt+ " ");
 
}
}
 
// This code is contributed by shikhasingrajput

Python3

# Python program of the above approach
from collections import defaultdict
 
class Solution:
     
    # Function to find smallest set
    # of vertices from which the
    # complete graph can be visited
    def solve(self , edges):
 
        graph = defaultdict(list)
 
        # dictionary storing
        # indgree of nodes
        indeg = defaultdict(int)
 
        for (u,v) in edges:
            graph[u].append(v)
 
            # count indegree of
            # each node
            indeg[v] +=1
 
        ans = []
        for u in graph:
             
            # add to ans, if indegree
            # of node u is 0
            if(indeg[u] == 0):
                ans.append(u)
 
        # Return Ans
        return (ans)
             
 
obj = Solution()
edges = [[0,1] , [2,1] , [3,2] , [4,3] ]
 
ans= obj.solve(edges)
print(" ".join(str(n) for n in ans))

C#

// C# program of the above approach
using System;
using System.Collections.Generic;
 
public class GFG {
 
    // Function to find smallest set
    // of vertices from which the
    // complete graph can be visited
    static List solve(int[, ] edges)
    {
        Dictionary graph
            = new Dictionary();
 
        // Dictionary storing
        // indgree of nodes
        Dictionary indeg
            = new Dictionary();
        for (int k = 0; k < edges.GetLength(0); k++) {
            int keys = edges[k, 0];
            int values = edges[k, 1];
            graph.Add(keys, values);
 
            // Count indegree of
            // each node
            if (indeg.ContainsKey(values)) {
                indeg[values] += 1;
            }
            else
                indeg.Add(values, 1);
        }
 
        List ans = new List();
        foreach(KeyValuePair it in graph)
        {
 
            // Add to ans, if indegree
            // of node u is 0
            if (!indeg.ContainsKey(it.Key))
                ans.Add(it.Key);
        }
 
        // Return Ans
        return ans;
    }
    public static int[] GetRow(int[, ] matrix, int row)
    {
        var rowLength = matrix.GetLength(1);
        var rowVector = new int[rowLength];
 
        for (var i = 0; i < rowLength; i++)
            rowVector[i] = matrix[row, i];
 
        return rowVector;
    }
   
    // Driver code
    public static void Main(String[] args)
    {
        int[, ] edges
            = { { 0, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 } };
 
        List ans = solve(edges);
        foreach(int dt in ans) Console.Write(dt + " ");
    }
}
 
// This code is contributed by 29AjayKumar
输出
0 4

时间复杂度: O(N)
辅助空间: O(N)