分析:该题属于求无向图中的连通域的个数 类的题目,面对该种题目,我们通常可以选择的方法有DFS/BFS/并查集
我们使用图搜索算法从各个连通域的任一顶点开始遍历整个连通域,遍历的过程中对 visited 数组进行标记,遍历完当前连通域之后,若仍有顶点未被访问,说明又是一个新的连通域,使用 cnt 累计当前遍历过的连通域的数量
简单来说就是遇到一个没搜索过的城市,我们就DFS/BFS它,然后把所有与该城市相联系的城市的visited标记,然后再回去看还有没有没被标记的城市,如果有,那就还有省份可以++,反之没有
解法一:深度优先搜索(DFS)
#include<iostream>
void dfs(vector<vector<int> >& isConnected, int visited[], int j)
{
visited[j] = 1;
for (int z = 0; z < isConnected.size(); z++)
{
if (isConnected[j][z]&&!visited[z])//如果这个城市没来过并且与j城市相连
{
visited[z] = 1;//记录来过
dfs(isConnected, visited, z);//搜索下一个
}
}
}
int main()
{
int visited[200] = { 0 };
int cn = 0;
vector<vector<int> >isConnected = { {1,1,0},{1,1,0},{0,0,1} };
int n = isConnected.size();//城市数量
for (int i = 0; i < n; i++)//遍历所有城市
{
if (!visited[i])//如果这个城市没来过
{
visited[i] = 1;//记录来过
cn++;//省份++
dfs(isConnected, visited, i);//搜索与其相连的城市
}
}
cout << cn << endl;
return 0;
}
解法二:广度优先搜索(BFS)
BFS与DFS的思路一致
class Solution {
public:
int findCircleNum(vector<vector<int>>& isConnected) {
int visited[201] = { 0 };
int n = isConnected.size();
int cn = 0;
queue<int> q;
for (int i = 0; i < n; i++)
{
if (!visited[i])
{
cn++;
q.push(i);
while (!q.empty())
{
int now = q.front();
q.pop();
visited[now] = 1;
for (int j = 0; j < n; j++)
{
if (!visited[j] && isConnected[now][j])
{
visited[j] = 1;
q.push(j);
}
}
}
}
}
return cn;
}
};
解法三:并查集
图的顶点数为 n,则初始化 n 个单顶点集合,每个集合指向自身。然后遍历图中的每个顶点,将当前顶点与其邻接点进行合并。最终结果返回合并后的集合的数量即可。
class Solution {
public:
int father[201];
void init(int n)//初始化
{
for(int i=0;i<n;i++)
{
father[i]=i;
}
}
int find(int i)
{
if(father[i]==i)
{
return i;
}
else
{
return father[i]=find(father[i]);//递归实现路径压缩同时找 根
}
}
void join(int x,int y)
{
int root1=find(x);
int root2=find(y);
if(root1!=root2)
{
father[root1]=root2;//注意这里容易搞错,是将一个根节点作为另一个根节点的根节点
}
}
int getans(int n)//计算不同的根有多少(根 即省份)
{
set<int> ans;
for(int i=0;i<n;i++)
{
ans.insert(find(i));
}
return ans.size();
}
int findCircleNum(vector<vector<int>>& isConnected) {
int n=isConnected.size();//几个根节点
init(n);//初始化
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)//各个城市循环比较
{
if(isConnected[i][j])//如果两个城市直接相连
{
join(i,j);//并 起来
}
}
}
return getans(n);
}
};
如果对上述算法有不了解的