并查集例题

栏目: 数据库 · 发布时间: 5年前

内容简介:合并的时候考虑的点比较多,假如当前修好的计算机编号是p,合并需要同时满足三个条件:1.合并的计算机编号不是p;2.合并的计算机与p的距离小于等于d;3.合并的计算机也是好的

POJ 2236

并查集例题 很水的并查集题目,结构体中除了存坐标x,y以外还要存是否被维修过

合并的时候考虑的点比较多,假如当前修好的计算机编号是p,合并需要同时满足三个条件:1.合并的计算机编号不是p;2.合并的计算机与p的距离小于等于d;3.合并的计算机也是好的

import java.util.*;

public class Main {
    public static class Node {
        int x, y;
        boolean isGood;

        Node(int x, int y, boolean isGood) {
            this.x = x;
            this.y = y;
            this.isGood = isGood;
        }
    }

    public static class unionFindSet {
        public HashMap<Node, Node> fatherMap;
        public HashMap<Node, Integer> sizeMap;

        public unionFindSet() {
            fatherMap = new HashMap<Node, Node>();
            sizeMap = new HashMap<Node, Integer>();
        }

        public void makeSets(List<Node> nodes) {
            fatherMap.clear();
            sizeMap.clear();
            for (Node node : nodes) {
                fatherMap.put(node, node);
                sizeMap.put(node, 1);
            }
        }

        private Node findHead(Node node) {
            Node father = fatherMap.get(node);
            if (father != node)
                father = findHead(father);
            fatherMap.put(node, father);
            return father;
        }

        public boolean isSameSet(Node a, Node b) {
            return findHead(a) == findHead(b);
        }

        public void union(Node a, Node b) {
            if (a == null || b == null) {
                return;
            }
            Node aHead = findHead(a);
            Node bHead = findHead(b);
            if (aHead != bHead) {
                int aSetSize = sizeMap.get(aHead);
                int bSetSize = sizeMap.get(bHead);
                if (aSetSize <= bSetSize) {
                    fatherMap.put(aHead, bHead);
                    sizeMap.put(bHead, aSetSize + bSetSize);
                } else {
                    fatherMap.put(bHead, aHead);
                    sizeMap.put(aHead, aSetSize + bSetSize);
                }
            }
        }
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int d = cin.nextInt();
        unionFindSet ufd = new unionFindSet();
        List<Node> list = new LinkedList<Node>();
        for (int i = 0; i < n; i++) {
            int x = cin.nextInt();
            int y = cin.nextInt();
            list.add(new Node(x, y, false));
        }
        ufd.makeSets(list);
        while (cin.hasNext()) {
            String start = cin.next();
            if (start.equals("O")) {
                int p = cin.nextInt();
                Node a = list.get(p - 1);
                a.isGood = true;
                list.set(p - 1, a);
                for (int i = 0; i < list.size(); i++)
                    if (i != p - 1 && list.get(i).isGood && distance(a, list.get(i)) <= d * d)
                        ufd.union(a, list.get(i));
            } else if (start.equals("S")) {
                int p = cin.nextInt();
                int q = cin.nextInt();
                if (ufd.isSameSet(list.get(p - 1), list.get(q - 1)))
                    System.out.println("SUCCESS");
                else
                    System.out.println("FAIL");
            }
        }
    }

    static double distance(Node a, Node b) {
        return Math.pow((a.x - b.x), 2) + Math.pow((a.y - b.y), 2);
    }
}

POJ 1182

并查集例题 经典的种类并查集问题,我在这道题上卡了至少有一个星期才搞懂

比较简单的并查集开一倍空间存节点即可,但是这道题需要开三倍空间,我们把这三个空间分别记为A、B、C,对于任意一只动物,三个空间中都存有,比方说总共有N只动物,第i只动物的编号是i,那么在A、B、C三个空间中的编号分别为i、i + N、i + (N << 1)

这三个空间A、B、C之间相互有一定的关系,A中的所有动物吃B中的所有动物;B中的所有动物吃C中的所有动物;C中的所有动物吃A中的所有动物

在不考虑矛盾的情况下,合并同种动物a和b的代码如下

conn(a, b)
conn(a + N, b + N)
conn(a + (n << 1), b + (n << 1))

上面代码很好理解,就是将A空间内的a和b,以及B空间内的a和b;C空间内的a和b合并

由于三个空间具有相互捕食的关系,因此如果有动物a吃动物b,他们之间的合并代码应该如下所示

conn(a, b + N)
conn(a + N, b + (n << 1))
conn(a + (N << 1), b)

如果这里不理解,就回过头仔细看看A、B、C三个空间的关系

上面是不考虑矛盾的情况,实际上在所有的合并之前,应该考虑会不会存在矛盾,下面我们探讨如何判断矛盾

假设动物a和b是同一物种,那就去查询a和b + N、a和b + (N << 1)是否在同一个集合内,前者判断的是a是否吃b,后者判断的是b是否吃a,只要这两者满足其一,就和当前的操作矛盾(当前操作是a与b是同一物种)

假设a吃b,那就去查询a和b、a和b + (N << 1)是否在同一集合内,前者判断a和b是否是同一物种,后者判断b是否吃a(不可能存在a吃b,b也吃a),只要这两者满足其一,就和当前的操作矛盾(当前操作是a吃b)

#include <iostream>
using namespace std;
int n, m;
int f[150004];
int size[150004];
int find(int a) {
    if (f[a] == a)
        return a;
    return f[a] = find(f[a]);
}
bool same(int a, int b) {
    return find(a) == find(b);
} 
void conn(int a, int b) {
    int fa = find(a);
    int fb = find(b);
    if (fa != fb) {
        int sa = size[fa];
        int sb = size[fb];
        if (sa <= sb) {
            f[fa] = fb;
            size[fb] = sa + sb; 
        } else {
            f[fb] = fa;
            size[fa] = sa + sb;
        }
    }
} 
int main() {
    int ans = 0;
    scanf("%d %d", &n, &m);
    for (int i = 0; i <= (n << 1) + n; i++) {
        f[i] = i; 
        size[i] = 1;
    }
    for (int i = 0; i < m; i++) {
        int op, a, b;
        scanf("%d %d %d", &op, &a, &b);
        if (a > n || b > n || a < 1 || b < 1)
            ans++;
        else if (op == 2 && a == b)
            ans++;
        else if (op == 1) {
            if (same(a, b + n) || same(a, b + (n << 1)))
                ans++;
            else {
                conn(a, b);
                conn(a + n, b + n);
                conn(a + (n << 1), b + (n << 1));
            }
        } else {
            if (same(a, b) || same(a, b + (n << 1)))
                ans++;
            else {
                conn(a, b + n);
                conn(a + n, b + (n << 1));
                conn(a + (n << 1), b);
            }
        }
    }
    printf("%d\n",ans);
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

文本上的算法——深入浅出自然语言处理

文本上的算法——深入浅出自然语言处理

路彦雄 / 人民邮电出版社 / 2018-3-1 / 69.00元

本书结合作者多年学习和从事自然语言处理相关工作的经验,力图用生动形象的方式深入浅出地介绍自然语言处理的理论、方法和技术。本书抛弃掉繁琐的证明,提取出算法的核心,帮助读者尽快地掌握自然语言处理所必备的知识和技能。本书主要分两大部分。第一部分是理论篇,包含前3章内容,主要介绍一些基础的数学知识、优化理论知识和一些机器学习的相关知识。第二部分是应用篇,包含第4章到第8章,分别针对计算性能、文本处理的术语......一起来看看 《文本上的算法——深入浅出自然语言处理》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具