zoukankan      html  css  js  c++  java
  • 并查集

    推荐:http://blog.csdn.net/dellaserss/article/details/7724401/

    int father[maxn], size[maxn];
    int fintFatherD(int x) {
        if (x == father[x]) {
            return x;
        } else {
            return father[x] = findFatherD(father[x]);
        }
    }//路径压缩 
    int findFather(int x) {
        int p, q;
        for (p = x; p != father[p]; p = father[p]);
        for (; x != p; q = father[x], father[x] = p, x = q);
        return p;
    }//启发式合并 
    void init(int n) {
        for (int i = 1; i <= n; ++ i) {
            father[i] = i;
            size[i] = 1;
        }
    }//初始化 一开始每个人的父亲都是自己 
    void joinSets(int a, int b) {
        a = findFather(a);
        b = findFather(b);
        if (size[a] < size[b]) {
            swap(a, b);
        }
        father[b] = a;
        size[a] += size[b];
    }//把元素少的合并到元素大的  只后再把小的爸爸变成大的那个爸爸 

     例题:维护一个集合,支持插入一个数,查询一个数字前驱

    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn = 1000003;
    int n, m, father[maxn], op[maxn], ans[maxn];
    int findRoot(int x) {
        int p, q;
        for (p = x; p != father[p]; p = father[p]);
        for (; x != p; q = father[x], father[x] = p, x = q);
        return p;
    }
    void init(int n) {
        for (int i = 1; i <= n; ++ i) {
            father[i] = i - 1;
            size[i] = 1;
        }
    }
    int main() {
        cin >> n >> m;
        init(n);
        for (int i = 0; i < m; ++ i) {
            int opt, v;
            cin >> opt >> v;
            if (opt == 1) { // 插入
                father[v] = v;
                op[i] = -v;
            } else { // 查询
                op[i] = v;
            }
        }
        for (int i = m - 1; i >= 0; -- i) {
            if (op[i] < 0) { // 插入,现在要删除它
                father[-op[i]] = -op[i] - 1;
            } else { // 查询前趋
                ans[i] = findRoot(op[i] - 1);
            }
        }
        for (int i = 0; i < m; ++ i) {
            if (ans[i]) {
                cout << ans[i] << endl;
            }
        }
    }//反向做题 先假设全部插入 之后倒序删除 答案再倒序输出 就是正的了 
    //op数组记录操作 前驱就是集合中比他小的最大的数
  • 相关阅读:
    屏幕尺寸相关
    关于sqlite的数据库操作
    Service服务
    BroadcastReceiver广播接收器
    将博客搬至CSDN
    win7+WinDbg调试系统内核
    驱动
    驱动开发,走起!!哈哈
    动态链接库DLL
    2013年12月24号感受
  • 原文地址:https://www.cnblogs.com/9pounds15pence/p/6349627.html
Copyright © 2011-2022 走看看