省份数量(DFS/BFS/并查集)

 分析:该题属于求无向图中的连通域的个数 类的题目,面对该种题目,我们通常可以选择的方法有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);
    }
};

如果对上述算法有不了解的

来这DFS(深度优先搜索算法)入门

来这BFS(广度优先搜索算法)入门

来这并查集

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ZZZWWWFFF_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值