zoukankan      html  css  js  c++  java
  • 洛谷P1196 [NOI2002]银河英雄传说 题解 并查集

    题目链接:https://www.luogu.com.cn/problem/P1196

    题目大意:
    一开始有 (30000) 个元素,每个元素组成一个队列。
    (T) 次操作((1 le T le 500000)),操作分类两种类型:

    1. 修改操作“M i j”:将 (i) 所处的队列,作为一个整体接至 (j) 所处的队列的尾部;
    2. 询问操作“C i j”:询问 (i)(j) 是否处于同一队列中,如果存在同一队列中,那么请问 (i)(j) 之间隔了多少个元素?

    解题思路:
    多开一个dist数组,(dist[i]) 用于表示 (i) 距离当前队首元素(集合的根节点)的距离,然后路径压缩的时候更新一下 (dist[i]) 即可。

    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int n = 30000;
    int f[n+1], dist[n+1], sz[n+1], T, i, j;
    char op[2];
    void init() {
        for (int i = 1; i <= n; i ++) {
            f[i] = i;       // f[i]表示i的根节点
            dist[i] = 0;    // dist[i]表示i距根节点的距离
            sz[i] = 1;      // dist[i]表示i为根节点的集合中元素个数
        }
    }
    int func_find(int x) {
        int p = f[x];
        if (x == p) return x;
        f[x] = func_find(p);
        dist[x] += dist[p];
        return f[x];
    }
    void func_union(int x, int y) { // 将x所在的队列合并到y所在的队列后面
        int a = func_find(x), b = func_find(y);
        dist[a] = sz[b];
        sz[b] += sz[a];
        f[a] = b;
    }
    int main() {
        init();
        scanf("%d", &T);
        while (T --) {
            scanf("%s%d%d", op, &i, &j);
            if (op[0] == 'M') {
                func_union(i, j);
            }
            else {
                if (func_find(i) != func_find(j)) puts("-1");
                else printf("%d
    ", abs(dist[i]-dist[j])-1);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    perl next和last
    用 Flask 来写个轻博客 (26) — 使用 Flask-Celery-Helper 实现异步任务
    mysql 更新唯一主键列 被堵塞
    perl + 匹配前导模式一次或者多次
    跨域
    日志处理
    FineBI:一个简单易用的自助BI工具
    FineBI:一个简单易用的自助BI工具
    bootstrap-treeview
    Bootstrap树形菜单插件TreeView.js使用方法详解
  • 原文地址:https://www.cnblogs.com/quanjun/p/12246484.html
Copyright © 2011-2022 走看看