2025计算机能力挑战赛初赛Java(编程第二题)

声明:本文仅作为算法题目分享和学习交流使用,若内容存在侵权行为,请及时私信联系,我们将立即删除。

问题描述(回忆题目,可能存在不完整)

有 n 个城市,初始时所有城市之间都没有建立联系。系统会进行 q 次操作,操作分为两种类型:

  1. 建立联系(操作类型为 1):在城市 x 和城市 y 之间建立联系

  2. 查询联系(操作类型为 2):查询城市 x 和城市 y 是否已经建立了联系(包括直接或间接联系)

对于每个查询操作,如果两个城市已经建立了联系,则输出 "Yes x y"(x 和 y 是查询的两个城市);如果没有建立联系,则输出 "No"。

输入格式

第一行包含两个整数 n 和 q,分别表示城市的数量和操作的数量。

接下来 q 行,每行包含三个整数:

  • 第一个整数是操作类型 a(1 或 2)

  • 第二个整数是城市 x

  • 第三个整数是城市 y

输出格式

对于每个查询操作(操作类型为 2),输出一行结果:

  • 如果两个城市已建立联系,输出 "Yes x y"

  • 如果两个城市未建立联系,输出 "No"

仅供参考(不是官方正确答案)

import java.util.*;

public class Main {
    private static int[] parent;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 读取城市数量和操作数量
        int n = scanner.nextInt();
        int q = scanner.nextInt();

        // 初始化并查集
        parent = new int[n];
        for (int i = 0; i < n; i++) {
            parent[i] = i;  // 初始时每个城市都是独立的,父节点指向自己
        }

        // 处理每个操作
        for (int i = 0; i < q; i++) {
            int operation = scanner.nextInt();
            int x = scanner.nextInt();
            int y = scanner.nextInt();

            // 城市编号从1开始,调整为从0开始
            x--;
            y--;

            if (operation == 1) {
                // 建立联系操作:合并两个城市
                union(x, y);
            } else if (operation == 2) {
                // 查询联系操作:检查两个城市是否连通
                if (find(x) == find(y)) {
                    // 注意输出时要还原城市编号(从1开始)
                    System.out.println("Yes " + (x + 1) + " " + (y + 1));
                } else {
                    System.out.println("No");
                }
            }
        }

        scanner.close();
    }

    // 查找根节点(带路径压缩)
    private static int find(int x) {
        if (parent[x] != x) {
            parent[x] = find(parent[x]); // 路径压缩:直接连接到根节点
        }
        return parent[x];
    }

    // 合并两个集合
    private static void union(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);

        if (rootX != rootY) {
            parent[rootY] = rootX; // 将y的根节点连接到x的根节点
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值