We are a team - 华为OD统一考试

OD统一考试

题解: Java / Python / C++

alt

题目描述

总共有 n 个人在机房,每个人有一个标号 (1<=标号<=n) ,他们分成了多个团队,需要你根据收到的 m 条消息判定指定的两个人是否在一个团队中,具体的:

  1. 消息构成为 a b c,整数 a、b 分别代表两个人的标号,整数 c 代表指令。
  2. c== 0 代表a和b在一个团队内。
  3. c == 1 代表需要判定 a 和b 的关系,如果 a和b是一个团队,输出一行"we are a team",如果不是,输出一行"we are not a team"。
  4. c 为其他值,或当前行a或b 超出 1~n 的范围,输出 "da pian zi"。

输入描述

  1. 第一行包含两个整数 n,m(1<=n.m<=100000).分别表示有n个人和 m 条消息。
  2. 随后的 m 行,每行一条消息,消息格式为: a b c (1<=a,b<=n, 0<=c<=1)

输出描述

  1. c ==1.根据 a 和 b 是否在一个团队中输出一行字符串,在一个团队中输出 "we are a team", 不在一个团队中输出 "we are not a team"。
  2. c 为其他值,或当前行 a 或 b 的标号小于 1 或者大于 n 时,输出字符串 "da pian zi"。
  3. 如果第一行 n 和 m的值超出约定的范围时,输出字符串"NULL"。

示例1

输入
5 6
1 2 0
1 2 1
1 5 0
2 3 1
2 5 1
1 3 2

输出
we are a team
we are not a team
we are a team
da pian zi

题解

并查集的简单模板套用

如果对并查集不会,可以通过 https://zhuanlan.zhihu.com/p/93647900 来学习。

Java

import java.util.Scanner;
public class Main {

    private static boolean checkRange(int a, int b, int c) {
        return 1 <= a && a <= 100000 && 1 <= b && b <= 100000 && 0 <= c && c <= 1;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt(), m = scanner.nextInt();
        if (!checkRange(n, m, 0)) {
            System.out.println("NULL");
            return;
        }

        UnionFind uf = new UnionFind(n);
        for (int i = 0; i < m; i++) {
            int a = scanner.nextInt(), b = scanner.nextInt(), c = scanner.nextInt();
            if (checkRange(a, b, c)) {
                if (c == 0) {
                    uf.merge(a, b);
                } else if (uf.find(a) == uf.find(b)) {
                    System.out.println("we are a team");
                } else {
                    System.out.println("we are not a team");
                }
            } else {
                System.out.println("da pian zi");
            }
        }
    }

}

/**
 * 并查集
 *
 * @Description: 学习参考: https://zhuanlan.zhihu.com/p/93647900
 * @Author code5bug
 * @Date 20-10-22
 * @Version 1.0
 **/
class UnionFind {
    // father[2] = 3 表示元素2的父节点是3
    public int[] father;

    public UnionFind(int len) {
        father = new int[len + 1];
        for (int i = 1; i <= len; i++) {
            father[i] = i;
        }
    }

    // 查询 x 的根节点
    public int find(int x) {
        if (x < 0 || x >= father.length) {
            throw new RuntimeException("查询越界");
        }

        // 合并(路径压缩)
        return (x == father[x] ? x : (father[x] = find(father[x])));
    }

    // 合并节点, y 的根节点指向 x 的根节点
    public void merge(int x, int y) {
        int xRoot = find(x), yRoot = find(y);
        father[yRoot] = xRoot;
    }
}

Python

n, m = map(int, input().split())


def check_range(a: int, b: int, c=0) -> bool:
    return 1 <= a <= 100000 and 1 <= b <= 100000 and 0 <= c <= 1


if check_range(n, m):
    fa = [i for i in range(n + 1)]

    def find(x: int) -> int:
        if fa[x] != x:
            fa[x] = find(fa[x])
        return fa[x]

    def merge(x: int, y: int):
        x_root, y_root = find(x), find(y)
        fa[x_root] = y_root

    for _ in range(m):
        a, b, c = map(int, input().split())
        if check_range(a, b, c):
            if c == 0:
                merge(a, b)
            elif find(a) == find(b):
                print("we are a team")
            else:
                print("we are not a team")
        else:
            print("da pian zi")
else:
    print("NULL")

C++

#include <iostream>
#include <vector>

using namespace std;

bool check_range(int a, int b, int c = 0) {
    if(a < 1 || b < 1 || c < 0) return false;
    if(a > 100000 || b > 100000 || c > 1) return false;
    return true;
}


int find(vector<int>& fa, int x) {
    if(fa[x] != x) {
        fa[x] = find(fa, fa[x]);
    }
    return fa[x];
}

int merge(vector<int>& fa, int x, int y) {
    int xRoot = find(fa, x), yRoot = find(fa, y);
    fa[xRoot] = yRoot;
}

int main() {
    int n, m;
    cin >> n >> m;

    if(!check_range(n, m)) {
        cout << "NULL" << endl;
        return -1;
    }

    vector<int> fa(n+1);
    for(int i=0; i<=n; i++) fa[i] = i;

    for(int i=0, a, b, c; i<m; i++) {
        cin >> a >> b >> c;
        if(check_range(a, b, c)) {
            if(c == 0) {
                merge(fa, a, b);
            } else if(find(fa, a) == find(fa, b)) {
                cout << "we are a team" << endl;
            } else {
                cout << "we are not a team" << endl;
            }
        } else {
            cout << "da pian zi" << endl;
        }
    }

    return 0;
}

(并查集)相关练习题

alt

🙏整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

#面经##秋招##春招##华为##校招#
全部评论

相关推荐

拒绝996的悲伤蛙:此贴终结|给路过的牛友分享一下心得👇 实习的时候不要光埋头干活,身边的大佬同事才是真·宝藏人脉!大胆请教他们工作以及职场上的问题以我的经历,我的带教有十几年工作经验,做过运维、后端开发、web测试,现在是高级软测,是行走的避坑指南 我之前纠结要不要学Web测试简历,被他一句话点醒:Web发展成熟,岗位需求在缩,AI对互联网的冲击可能以后架构+开发+测试一人包揽。现在用户更多用的是移动端APP/小程序,相比之下天天守着电脑刷网页的人基数小。 这里我的纠结得到反馈,于是我又把简历发给带教,获得了一对一的简历指导。 感兴趣的可以看看: 1.教育背景:本科→本科(全日制) 2.实习经历:总体问题不大,但第2点要稍作修改,可以写但做功课,如风机、水箱……可能会问用哪个供应商的?使用寿命、型号、电压电流、多少秒会触发逻辑? 3.项目经历(坑太多,大型翻车现场): - 项目名越直白越好,让人一眼就知道你干了啥。 -用的什么语言设计核心接口,异步执行做功课,涉及线程问题,被问可回答n个功能是如何错开异步执行的 - “验证任务消费……阻塞丢包”“高负载稳定性”这种词,没三五年开发功底不要写,不然面试时被问线程、数量级、CPU占用,内存带宽等影响性能的直接原地社死。 -做功课 -做功课,测了哪些模块,如何设计,接口流量抓包,token,变量…… -做功课,要熟悉网络协议…… 带教之前做互联网开发的时候面试过很多人,总的来说不要为了显得项目高大上过渡包装,写了就要做好拷打的准备
听劝,我这个简历该怎么改...
点赞 评论 收藏
分享
评论
3
5
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务