Graph 有向图中有多少个组件?

Graph 有向图中有多少个组件?,graph,Graph,我有以下图表: 最佳解决方案是从顶点(3)开始dfs,然后我将得到一个组件,但当我们从顶点(1)开始dfs时,然后(3)我将得到两个组件。 问题是: 我想知道这个图中有多少个组件?或者从另一方面讲,覆盖所有图表所需的dfs的最小数量是多少 执行此操作所需的算法是什么?您混淆了两个定义 对于无向图,有一个概念,您可以通过对无向图执行DFS来找到它 对于有向图,有多个算法可用的概念,都比简单的DFS稍微复杂一些 你应该做什么取决于你需要这两个概念中的哪一个。当作为无向图查看时,图形有一个连通组件,

我有以下图表:

最佳解决方案是从顶点(3)开始dfs,然后我将得到一个组件,但当我们从顶点(1)开始dfs时,然后(3)我将得到两个组件。 问题是: 我想知道这个图中有多少个组件?或者从另一方面讲,覆盖所有图表所需的dfs的最小数量是多少


执行此操作所需的算法是什么?

您混淆了两个定义

对于无向图,有一个概念,您可以通过对无向图执行DFS来找到它

对于有向图,有多个算法可用的概念,都比简单的DFS稍微复杂一些


你应该做什么取决于你需要这两个概念中的哪一个。当作为无向图查看时,图形有一个连通组件,当作为有向图查看时,图形有两个强连通组件。

要解决此问题,请使用边的邻接列表

以一个具有3个节点和2条边(0,1)和(0,2)的图为例,而(a,b)表示如果切换灯a,则灯b也将切换

OUT-edges adjacency list:
0 -> 1, 2
1 -> _
2 -> _

IN-edges adjacency list:
0 -> _
1 -> 0
2 -> 0
假设我们没有循环,如果我们沿着IN边向下走,直到到达一个没有子节点的节点,你会得到我所说的“影响者”,也就是说,你不能将它与任何其他节点切换

现在考虑到周期,我检查是否有邻居有或是影响者。如果情况并非如此,并且所有邻居都已经访问过,我会遇到一个循环,并使当前节点成为影响者

这是我的代码(在我的桌面上用简单的示例进行测试):

private int numberOfLights(){
扫描仪=新的扫描仪(System.in);
int n=scanner.nextInt();
List inAdjList=new ArrayList();
对于(int i=0;i

希望有帮助!:)

您可以从每个节点运行findConnectedComponent算法,并返回最小数目以解决特定问题。
我认为这个解决方案不是最优的,但它在中小型输入图形中运行得非常好。

我为这个问题奋斗了好几个星期 最后,当我在上一次的编码竞赛中遇到一个问题时,我找到了解决方案

解决问题的过程:

  • 执行拓扑排序,然后对获得的排序结果执行DFS。您必须调用DFS的次数是连接的组件数
在您的情况下,在进行拓扑排序后,我们得到3 1 2 4 现在再次根据此排序值运行DFS(此处从3开始),您将得到ans 1


希望有帮助:)我相信您正在尝试查找弱连接组件。
测试有向图是否弱连通可以很容易地在线性时间内完成。只需将所有边转换为无向边,并使用基于DFS的连接组件算法。

我知道这是一个旧线程,但添加我解决问题的方法会很有帮助:

1-找到图中的强连接组件(SCC),对于每个SCC,我们可以将其替换为表示该SCC的单个节点


2-现在,通过查看新图表中节点的度数,我们可以知道可以运行DFS的最小节点数,并覆盖所有其他节点,因此我们可以从度数为零的节点启动DFS,但还有另一种方法

  • 通过在所有节点上执行DFS,将有向图转换为无向图。O(V+E)
  • 做你们为无向图所做的。O(V+E)

  • 我的问题是:我需要在图上执行dfs,但我需要覆盖所有图的最少dfs调用数。例如,当调用dfs(3)时,这将覆盖所有图形,然后我们在此处调用一个,但当调用dfs(1)时,这将仅覆盖三个节点,因此我们需要调用另一个dfs(3)来覆盖所有图形。谢谢你的回答。@MohammadShahoud:你真的需要有向图吗?你就不能把边缘向后看吗?这就是我要问的问题的联系:我经常面临同样的问题。如果在1、2或4上执行正常dfs,则连接的组件中不计算3,并且我们无法确保dfs始终从4开始(循环中不包括节点)。我仍然不知道如何在这样的有向图上运行dfs来计算整个图中连接的组件的数量,这里显示的这个图可能是一个部分。这只在图是DAGyeah时有效,因为我们不会遇到像无向图中那样的问题:)
    private int numberOfLights(){
    
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
    
        List<List<Integer>> inAdjList = new ArrayList<List<Integer>>();
        for(int i = 0; i < n; i++){
            inAdjList.add(new ArrayList<>());
        }
    
    
        for(int i = 0; i < n; i++){
            int from = scanner.nextInt();
            int to = scanner.nextInt();
    
            inAdjList.get(to).add(from);
        }
    
        int[] visited = new int[n];
        int[] isOrHasInfluencer = new int[n];
        List<Integer> influencers = new ArrayList<>();
    
        for(int i = 0; i < n; i++){
            if(!visited[i]){
                DFS(i, visited, isOrHasInfluencer, influencers, inAdjList);
            }
        }
    
        return influencers.size();
    
    }
    
    private void DFS(Integer cur, int[] visited, int[] isOrHasInfluencer, List<Integer> influencers, List<List<Integer>> inAdjList){
    
        visited[cur] = true;
    
        boolean hasUnvisitedChildren = false;
        for(Integer neighbor : inAdjList.get(cur)){
    
            if(!visited[neighbor]){
                hasUnvisitedChildren = true;
                DFS(neighbor, visited, isOrHasInfluencer, influencers, inAdjList);
            }
    
            if(isOrHasInfluencer[neighbor]){
                isOrHasInfluencer[cur] = true;
            }
        }
    
        if(!hasUnvisitedChildren && !isOrHasInfluencer[cur]){
            isOrHasInfluencer[cur] = true;
            influencers.add(cur);
        }
    }