LeetCode 1319. 连通网络的操作次数(BFS/DFS/并查集)

1. 题目

用以太网线缆将 n 台计算机连接成一个网络,计算机的编号从 0 到 n-1。
线缆用 connections 表示,其中 connections[i] = [a, b] 连接了计算机 a 和 b。

网络中的任何一台计算机都可以通过网络直接或者间接访问同一个网络中其他任意一台计算机。

给你这个计算机网络的初始布线 connections,你可以拔开任意两台直连计算机之间的线缆,并用它连接一对未直连的计算机。
请你计算并返回使所有计算机都连通所需的最少操作次数。如果不可能,则返回 -1 。

在这里插入图片描述

示例 1:
输入:n = 4, connections = [[0,1],[0,2],[1,2]]
输出:1
解释:拔下计算机 12 之间的线缆,并将它插到计算机 13 上。

在这里插入图片描述

示例 2:
输入:n = 6, connections = [[0,1],[0,2],[0,3],[1,2],[1,3]]
输出:2

示例 3:
输入:n = 6, connections = [[0,1],[0,2],[0,3],[1,2]]
输出:-1
解释:线缆数量不足。

示例 4:
输入:n = 5, connections = [[0,1],[0,2],[3,4],[2,3]]
输出:0
 
提示:
1 <= n <= 10^5
1 <= connections.length <= min(n*(n-1)/2, 10^5)
connections[i].length == 2
0 <= connections[i][0], connections[i][1] < n
connections[i][0] != connections[i][1]
没有重复的连接。
两台计算机不会通过多条线缆连接。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-operations-to-make-network-connected
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题

  • 首先至少需要有n-1条连接,才可能满足题意
  • 其次,求有多少个集团,集团的个数-1就是需要改的线缆数量
  • 可以用BFS、DFS、并查集来求有多少个集团

2.1 BFS

class Solution {
	unordered_map<int,unordered_set<int>> m;
public:
    int makeConnected(int n, vector<vector<int>>& connections) {
    	if(connections.size() < n-1)
    		return -1;
    	vector<int> visited(n,false);
    	for(auto& c : connections)
    	{
    		m[c[0]].insert(c[1]);
    		m[c[1]].insert(c[0]);
    	}
    	int count = 0, tp;
        queue<int> q;
    	for(int i = 0; i < n; ++i)
    	{
    		if(!visited[i])
    		{
    			count++;
    			visited[i] = true;
    			q.push(i);
    			while(!q.empty())
    			{
    				tp = q.front();
    				q.pop();
    				for(auto c : m[tp])
    				{
    					if(!visited[c])
    					{
    						q.push(c);
    						visited[c] = true;
    					}
    				}
    			}
    		}
    	}
    	return count-1;
    }
};

432 ms 58.9 MB

2.2 DFS

class Solution {
	unordered_map<int,unordered_set<int>> m;
public:
    int makeConnected(int n, vector<vector<int>>& connections) {
    	if(connections.size() < n-1)
    		return -1;
    	vector<int> visited(n,false);
    	for(auto& c : connections)
    	{
    		m[c[0]].insert(c[1]);
    		m[c[1]].insert(c[0]);
    	}
    	int count = 0;
    	for(int i = 0; i < n; ++i)
    	{
    		if(!visited[i])
    		{
    			count++;
    			visited[i] = true;
    			dfs(i,visited);
    		}
    	}
    	return count-1;
    }
    void dfs(int i, vector<int>& visited)
    {
        for(auto c : m[i])
        {
            if(!visited[c])
            {
                visited[c] = true;
                dfs(c, visited);
            }
        }
    }
};

392 ms 59.4 MB

2.3 并查集

并查集参考:数据结构–并查集(Disjoint-Set)

扫描二维码关注公众号,回复: 11181425 查看本文章
class dsu
{
public:
    vector<int> f;
    dsu(int n)
    {
        f.resize(n);
        for(int i = 0; i < n; ++i)
            f[i] = i;
    }
    int find(int x)
    {
        if(x == f[x])
            return x;
        return f[x] = find(f[x]);
    }
    void merge(int x, int y)
    {
        int fx = find(x);
        int fy = find(y);
        f[fx] = fy;
    }
    int countuni()
    {
        int count = 0;
        for(int i = 0; i < f.size(); ++i)
        {
            if(i == find(i))
                count++;
        }
        return count;
    }
};

class Solution {
public:
    int makeConnected(int n, vector<vector<int>>& connections) {
    	if(connections.size() < n-1)
    		return -1;
    	dsu uni(n);
        for(auto& c : connections)
            uni.merge(c[0],c[1]);
        return uni.countuni()-1;
    }
};

176 ms 29 MB

可以看出并查集占用内存较少,运行时间较快。

原创文章 1053 获赞 4450 访问量 61万+

猜你喜欢

转载自blog.csdn.net/qq_21201267/article/details/106087256
今日推荐