美团 小美的朋友关系 Java

import java.util.*;
import java.io.*;

public class Main {
    // 并查集:父节点映射 + 秩映射(按秩合并用)
    public static HashMap<Integer, Integer> parent = new HashMap<>();
  
    // 查找(路径压缩 + 自动初始化节点)
    public static int find(int x) {
        // 节点不存在则初始化:父节点是自己,秩为1
        parent.putIfAbsent(x, x);
        // 路径压缩(迭代版,避免递归栈溢出)
        while (!parent.get(x).equals(x)) {
            parent.put(x, parent.get(parent.get(x))); // 父节点指向祖父节点
            x = parent.get(x);
        }
        return x;
    }

    // 合并(按秩合并 + 路径压缩)
    public static void merge(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX == rootY) return;

        // 按秩合并:将秩小的树合并到秩大的树
        parent.put(rootY, rootX);
    }

    // 生成统一的边key(避免{a,b}和{b,a}重复)
    static String getRelationKey(int a, int b) {
        return a < b ? a + "," + b : b + "," + a;
    }

    public static void main(String[] args) throws IOException {
        // 替换Scanner为BufferedReader,提升输入效率
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] parts = br.readLine().split(" ");
        int n = Integer.parseInt(parts[0]);
        int m = Integer.parseInt(parts[1]);
        int q = Integer.parseInt(parts[2]);

        // 存储原始边
        Set<String> edges = new HashSet<>();
        for (int i = 0; i < m; ++i) {
            parts = br.readLine().split(" ");
            int a = Integer.parseInt(parts[0]);
            int b = Integer.parseInt(parts[1]);
            edges.add(getRelationKey(a, b));
        }

        // 存储有效操作(过滤无效删除)
        ArrayList<int[]> ops = new ArrayList<>();
        for (int i = 0; i < q; ++i) {
            parts = br.readLine().split(" ");
            int op = Integer.parseInt(parts[0]);
            int a = Integer.parseInt(parts[1]);
            int b = Integer.parseInt(parts[2]);

            if (op == 1) {
                String key = getRelationKey(a, b);
                if (edges.contains(key)) {
                    edges.remove(key);
                    ops.add(new int[]{op, a, b});
                }
            } else {
                ops.add(new int[]{op, a, b});
            }
        }

        // 初始化:合并所有未被删除的边(最终状态)
        for (String key : edges) {
            String[] nodes = key.split(",");
            int a = Integer.parseInt(nodes[0]);
            int b = Integer.parseInt(nodes[1]);
            merge(a, b);
        }

        // 倒序处理操作,记录答案
        List<Boolean> answers = new ArrayList<>();
        for (int i = ops.size() - 1; i >= 0; i--) {
            int[] op = ops.get(i);
            if (op[0] == 1) {
                // 原删除操作 → 逆操作:合并
                merge(op[1], op[2]);
            } else {
                // 原查询操作:判断是否连通
                boolean connected = find(op[1]) == find(op[2]);
                answers.add(connected);
            }
        }

        // 逆序输出答案
        for (int i = answers.size() - 1; i >= 0; --i) {
            System.out.println(answers.get(i) ? "Yes" : "No");
        }
    }
}
全部评论

相关推荐

本周面试了快手社招技术终面,是个40多岁的女人,居然还是2个部门的最高领导,感觉是技术里面的高层,问的技术难题不多,主要是场景题,大概面了40分钟1&nbsp;面试官先自我介绍一下部门干的活,以及后续对于新人来了之后主要是要干啥,以及她对新人的一些要求2&nbsp;自我进行介绍,说一下你这边做的一些事情以及技术亮点3&nbsp;你说一下对于技术开发需要遵循哪些规范,你感觉作为技术人对于数据如何可以体现你的价值,以及你感觉技术如何给业务进行业务提升4&nbsp;对于一个湖仓架构,技术选型你优先会选择哪个,为啥会选择这个技术,这个对于别的优势体现在哪5&nbsp;如果要你来做一个实时数仓,你感觉对于实时数据精确一致性需要如何设计,对于技术如何体现难度6&nbsp;你做过财务数据和流量数据,你感觉这2方面的数据是有啥区别,对于技术来说如何选型,对于数据的指标哪些区别7&nbsp;你认为对于行为数据埋点可以怎么设计,对于埋点会出现啥问题,你平时对于埋点实时接入会有啥问题,对于数据来说如果埋点设计的不好有啥风险8&nbsp;你这边有啥需要找我理解的我感觉这个领导似乎对于技术不怎么面了,感觉是在问一些对于数据开发的思考和总体技术和风险评估,感觉像是在招一个职级比较高的人,面了大概40分钟,不知道能不能过,但我感觉有戏,过了再来更新
查看7道真题和解析
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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