#include <vector>
class Solution 
{
    // 访问标记数组:vis[i]为true表示第i个节点已被访问
    // 大小210是预设的最大节点数,适用于节点数量不超过210的场景
    bool vis[210] = {false};

public:
    // 计算图中连通分量的数量
    // 参数m:图的邻接矩阵表示,m[i][j]为非0值表示节点i和j相连
    int citys(vector<vector<int> >& m) 
    {
        int n = m.size();  // 获取节点数量(邻接矩阵的行数)
        int ret = 0;       // 记录连通分量的数量,初始为0

        // 遍历所有节点
        for(int i = 0; i < n; i++)
        {
            // 如果当前节点未被访问,说明发现了一个新的连通分量
            if(!vis[i])
            {
                ret++;              // 连通分量数量加1
                dfs(m, i);          // 从当前节点开始DFS,标记整个连通分量的节点为已访问
            }
        }
        return ret;  // 返回连通分量的总数
    }

    // 深度优先搜索(DFS):从pos节点出发,标记所有与其连通的节点
    // 参数m:邻接矩阵;pos:当前搜索的节点索引
    void dfs(vector<vector<int>>& m, int pos)
    {
        vis[pos] = true;  // 标记当前节点为已访问

        // 遍历所有节点,寻找与当前节点pos相连且未被访问的节点
        for(int i = 0; i < m.size(); i++)
        {
            // 条件:节点i未被访问,且节点pos与节点i相连(m[pos][i]非0)
            if(!vis[i] && m[pos][i])
            {
                dfs(m, i);  // 递归访问节点i,继续深入搜索
            }
        }
    } 
};

这段代码的核心功能是计算一个无向图中连通分量的数量。连通分量指的是图中 "相互连通的节点组成的最大子集"(即子集中的任意两个节点都能通过路径连接,且子集外的节点无法与子集内节点连接)。

  1. 数据结构与变量vis[210]:布尔数组,用于标记节点是否被访问过,避免重复处理同一节点邻接矩阵m:通过二维数组表示图,m[i][j]的值非零时,表示节点i和节点j之间有边相连
  2. 主函数citys的逻辑遍历所有节点,对每个未访问的节点:计数器ret加 1(发现新的连通分量)调用dfs函数,递归标记该连通分量的所有节点为 "已访问"最终返回ret,即连通分量的总数
  3. 辅助函数dfs的逻辑标记当前节点pos为已访问遍历所有节点,找到与pos相连且未访问的节点,递归调用dfs继续搜索作用是 "扩散式" 标记整个连通分量,确保每个连通分量只被计数一次