联通网络的操作次数(leetcode)

题目链接:1319. 连通网络的操作次数 - 力扣(LeetCode) (leetcode-cn.com)

题目描述:

用以太网线缆将 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] 没有重复的连接。 两台计算机不会通过多条线缆连接。

 

题目分析:

本题使用常规的并并查集方法,由于题目没有特定要求。

所以我们只需要求出连通分量个数和成环线的个数就可以得出答案。

值得注意的是 如果线的个数比连通分量个数多两个,那么输出的答案是连通分量个数-1,而非线的个数

源码:

#include<iostream>
#include<vector>
#include<unordered_map>
#include<cstring>
using namespace std;
int rank1[100000];
int parent[100000];
int find(int x)//
{
    while (parent[x] != -1)
    {
        x = parent[x];
    }
    return x;
}

int main()
{
    int n = 12;
    vector<vector<int>>connections = { {1, 5},{1, 7},{1, 2},{1, 4},{3, 7},{4, 7},{3, 5},{0, 6},{0, 1},{0, 4},{2, 6},{0, 3},{0, 2} };

    int line = 0;//可支配的线
    memset(parent, -1, sizeof(parent));
    memset(rank1, 0, sizeof(rank1));
    for (vector<int>x : connections)
    {
        int root1 = find(x[0]);
        int root2 = find(x[1]);
        if (root1 == root2)//找到循环节
        {
            line++;
        }
        else
        {
            if (rank1[root1] > rank1[root2])
                parent[root2] = root1;
            else if (rank1[root1] < rank1[root2])
                parent[root1] = root2;
            else
            {
                parent[root2] = root1;
                rank1[root2]++;
            }
        }
    }
    int flag = 0;
    for (int i = 0;i < n;i++)//找出游离节点个数
    {
        if (parent[i] == -1)
            flag++;
    }
    cout << (flag > line + 1 ? -1 : flag - 1);
}
/*
    int n = 6;
    vector<vector<int>>connections = { {0, 1}, { 0, 2}, { 0, 3}, { 1, 2}, { 1, 3} };
    2

    int n = 6;
    vector<vector<int>>connections = { {0, 1}, { 0, 2}, { 0, 3}, { 1, 2} };
    -1

    int n = 4;
    vector<vector<int>>connections = { {0, 1},{0, 2},{1, 2} };
    -1

*/

优化:

连通分量flag可以一开始就初始化为n,每连通一个就减一,

从而避免重新遍历parent数组。

原文地址:https://www.cnblogs.com/zjw1324399/p/14578565.html