城市连通性(200分 / 并查集)

题目描述 :有 n 个城市(编号 1 ~ n)和 m 条双向道路。每条道路连接两个城市。现在要判断:

  1. 这些城市是否全部连通(即任意两个城市之间都有路径)。

  2. 如果全部连通,输出 YES;否则输出需要最少新增多少条道路才能全部连通。

输入:

  • 第一行:n m(1 ≤ n ≤ 10^5,0 ≤ m ≤ 2×10^5)

  • 接下来 m 行:每行两个整数 u v,表示一条道路。

输出:

  • 若已全部连通:YES

  • 否则:一个整数,表示最少新增道路数。

示例:

text

复制代码
输入:
5 3
1 2
2 3
4 5

输出:
1

解释:连通分量为 {1,2,3} 和 {4,5},需要 1 条路连接两个分量。

解题思路

用并查集维护连通分量:

  • 初始每个城市独立,连通分量数 components = n。

  • 每合并两个不同集合,components--。

  • 最终若 components == 1,输出 YES;否则输出 components - 1(最少新增道路数 = 连通分量数 - 1)。

参考代码

c

复制代码
#include <stdio.h>

int parent[100005];
int rank_[100005];

int find(int x) {
    if (parent[x] != x)
        parent[x] = find(parent[x]); // 路径压缩
    return parent[x];
}

int unite(int a, int b) {
    int ra = find(a), rb = find(b);
    if (ra == rb) return 0;
    if (rank_[ra] < rank_[rb]) {
        parent[ra] = rb;
    } else if (rank_[ra] > rank_[rb]) {
        parent[rb] = ra;
    } else {
        parent[rb] = ra;
        rank_[ra]++;
    }
    return 1;
}

int main(void) {
    int n, m;
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++) {
        parent[i] = i;
        rank_[i] = 0;
    }

    int components = n;
    for (int i = 0; i < m; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        if (unite(u, v)) components--;
    }

    if (components == 1)
        printf("YES\n");
    else
        printf("%d\n", components - 1);

    return 0;
}
相关推荐
Gust of wind1 小时前
串与KMP模式匹配:存储结构、基本操作、next数组手算
c语言·数据结构·后端·算法
Navigator_Z1 小时前
LeetCode //C - 1283. Find the Smallest Divisor Given a Threshold
c语言·算法·leetcode
by209992 小时前
list:迭代器与资源管理实现的综合叙述(下)
数据结构·c++·笔记·list
啦啦啦啦啦zzzz2 小时前
一致性哈希
服务器·算法·哈希算法·c++20·分布式存储
我不会起名字3222 小时前
二叉树的遍历与二叉搜索树:把递归、迭代、还原树一次讲透
数据结构·leetcode·二叉树·二叉搜索树
垆边人似月.2 小时前
嵌入式传感器寄存器数据解析
算法
Tingmanyi2 小时前
YOLOv13改进策略【卷积层篇】| RFAConv 感受野注意力卷积,每个位置都值得被单独加权
深度学习·算法·yolo·目标检测·计算机视觉
yi0113 小时前
Leetcode 49 用 “身份证‘‘巧解
人工智能·笔记·python·算法·leetcode·哈希表
liuchangng3 小时前
类Jev项目Kev从入门到实战(7):如何选型:决策树与 checklist
算法·决策树·机器学习