图论算法——无向图的连通分量

博客介绍了深度优先搜索在找出无向图所有连通分量上的应用。阐述了连通分量是无向图的极大连通子图,添加外部顶点会造成不连通。还给出了通过标识连通分量的代码实现,部分代码实现可参考栈和队列的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

深度优先搜索的一个直接应用就是找出一幅图的所有连通分量。

在深度优先搜索的递归调用期间,只要是某个顶点的可达顶点都能在一次递归调用期间访问到。

有关图的概念可参考博文数据结构之图的概述

连通分量

连通分量:无向图的极大连通子图称为的连通分量( Connected Component)。

极大连通子图说的是,如果将连通分量外的任意一个顶点添加进连通分量都会造成不连通。

比如下图中有四个连通分量

lor_FFFFFF,t_70)

代码

通过id[]标识连通分量,同一连通分量的count值相同,count初始化为0

for (int s = 0; s < g.vertexNum(); s++) {
   if (!marked[s]) {
        //s的一次递归调用能访问所有与它连通的顶点
        dfs(g,s);
        //到这里说明s的连通顶点已经访问完毕
        count++;
    }
}

实现如下:

package com.algorithms.graph;

import com.algorithms.queue.Queue;

/**
 * 计算无向图的连通分量
 * @author yjw
 * @date 2019/5/22/022
 */
public class CC {
    private boolean[] marked;
    /**
     * 标识连通分量,同一连通分量的值相同
     * 0:第一个连通分量
     * 1:第二个连通分量
     * ...
     *
     * 值为0到count - 1之间
     */
    private int[] id;
    /**
     * 连通分量数
     */
    private int count;

    public CC(Graph g) {
        marked = new boolean[g.vertexNum()];
        id = new int[g.vertexNum()];
        for (int s = 0; s < g.vertexNum(); s++) {
            if (!marked[s]) {
                //s的一次递归调用能访问所有与它连通的顶点
                dfs(g,s);
                //到这里说明s的连通顶点已经访问完毕
                count++;
            }
        }
    }

    private void dfs(Graph g,int v) {
        marked[v] = true;
        id[v] = count;//标识连通分量
        for (int w: g.adj(v)) {
            if (!marked[w]) {
                dfs(g,w);
            }
        }
    }

    public boolean connected(int v,int w) {
        return id[v] == id[w];
    }

    public int id(int v) {
        return id[v];
    }

    public int count() {
        return count;
    }

    @SuppressWarnings("unchecked")
    public void print() {
        System.out.println(count + " components");//count个连通分量

        Queue<Integer>[]components = (Queue<Integer>[]) new Queue[count];
        for (int i = 0; i < components.length; i++) {
            components[i] = new Queue<>();
        }


        for (int i = 0; i < id.length; i++) {
            components[id(i)].enqueue(i);
        }
        for (Queue<Integer> queue : components) {
            System.out.println(queue);
        }

    }

    public static void main(String[] args) {
        Graph g = new Graph(10);
        g.addDiEdges(0,1,2);
        g.addDiEdges(4,5,6);
        g.addEdge(5,7);
        g.addEdge(8,9);

        //System.out.println(g);
        CC cc = new CC(g);
        cc.print();
    }
}

其中QueueStack的实现见 栈和队列的实现

我们对示例图计算连通分量,得到输出:

4 components
[0 1 2]
[3]
[4 5 6 7]
[8 9]
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愤怒的可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值