数据结构并查集2 --种类并查集

news/2024/11/17 6:01:57/
前置学习:
  • 数据结构并查集的学习

文章目录

  • 种类并查集
    • 实现
  • 例题
    • P1892 [BOI2003]团伙
      • 题目描述
      • 题解
    • [NOI2001] 食物链
      • 题目描述
      • 题解

种类并查集

种类并查集是拓展并查集的一种应用。普通并查集主要解决的是朋友的朋友是朋友的一类问题。而种类并查集则要解决敌人的敌人是朋友这样的一类问题。解决复杂的关系。

实现

多一个种族就开一倍的空间就可以了。
如敌人的敌人是朋友那么就只有2个种族就可以1-n表示一类,n-2n表示另一个类。
不同类中就是敌人同一个类就是朋友

简单来说就是有多少类就开多少倍的空间就可以了。

例题

P1892 [BOI2003]团伙

题目描述

现在有 n n n 个人,他们之间有两种关系:朋友和敌人。我们知道:

  • 一个人的朋友的朋友是朋友
  • 一个人的敌人的敌人是朋友

现在要对这些人进行组团。两个人在一个团体内当且仅当这两个人是朋友。请求出这些人中最多可能有的团体数。

输入格式

第一行输入一个整数 n n n 代表人数。

第二行输入一个整数 m m m 表示接下来要列出 m m m 个关系。

接下来 m m m 行,每行一个字符 o p t opt opt 和两个整数 p , q p,q p,q,分别代表关系(朋友或敌人),有关系的两个人之中的第一个人和第二个人。其中 o p t opt opt 有两种可能:

  • 如果 o p t opt optF,则表明 p p p q q q 是朋友。
  • 如果 o p t opt optE,则表明 p p p q q q 是敌人。

输出格式

一行一个整数代表最多的团体数。

样例 #1

样例输入 #1

6
4
E 1 4
F 3 5
F 4 6
E 1 2

样例输出 #1

3

提示

对于 100 % 100\% 100% 的数据, 2 ≤ n ≤ 1000 2 \le n \le 1000 2n1000 1 ≤ m ≤ 5000 1 \le m \le 5000 1m5000 1 ≤ p , q ≤ n 1 \le p,q \le n 1p,qn

题解

同类很好理解就用并查集就可以解决。
那么敌人的敌人怎么解决呢。
我们在开一倍空间来代表敌人。

如果 a 和 b 是敌人那么:

  • 让 a+n 指向 b
  • 让 b+n 指向 a

当在来一次的时候就会出现(如 a 和 c 是敌人)

  • a+n 和 c 合并 ,这时 c就和b一个集合了
  • c+n 指向 a

java代码

package com.yu;import java.io.*;
import java.util.stream.IntStream;public class Main {static final StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));public static String next() throws IOException {st.nextToken();return st.sval;}public static int nextInt() throws IOException {st.nextToken();return (int) st.nval;}public static int[] a;public static int find(int i) {if (a[i] == i) return i;else return a[i] = find(a[i]);}public static void union(int i, int j) {int x = find(i);int y = find(j);if (x != y) a[x] = y;}public static void main(String[] args) throws IOException {int n = nextInt();int k = nextInt();a = IntStream.range(0, 2 * n + 2).toArray();for (int i = 0; i < k; i++) {String opt = next();int p = nextInt();int q = nextInt();if ("E".equals(opt)) {union(q + n, p);union(p + n, q);} else {union(p, q);}}int ans = 0;for (int i = 1; i <= n; i++) {if (find(i) == i) ans++;}System.out.println(ans);}
}

[NOI2001] 食物链

题目描述

动物王国中有三类动物 A , B , C A,B,C A,B,C,这三类动物的食物链构成了有趣的环形。 A A A B B B B B B C C C C C C A A A

现有 N N N 个动物,以 1 ∼ N 1 \sim N 1N 编号。每个动物都是 A , B , C A,B,C A,B,C 中的一种,但是我们并不知道它到底是哪一种。

有人用两种说法对这 N N N 个动物所构成的食物链关系进行描述:

  • 第一种说法是 1 X Y,表示 X X X Y Y Y 是同类。
  • 第二种说法是2 X Y,表示 X X X Y Y Y

此人对 N N N 个动物,用上述两种说法,一句接一句地说出 K K K 句话,这 K K K 句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。

  • 当前的话与前面的某些真的话冲突,就是假话;
  • 当前的话中 X X X Y Y Y N N N 大,就是假话;
  • 当前的话表示 X X X X X X,就是假话。

你的任务是根据给定的 N N N K K K 句话,输出假话的总数。

输入格式

第一行两个整数, N , K N,K N,K,表示有 N N N 个动物, K K K 句话。

第二行开始每行一句话(按照题目要求,见样例)

输出格式

一行,一个整数,表示假话的总数。

样例 #1

样例输入 #1

100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5

样例输出 #1

3

提示

对于全部数据, 1 ≤ N ≤ 5 × 1 0 4 1\le N\le 5 \times 10^4 1N5×104 1 ≤ K ≤ 1 0 5 1\le K \le 10^5 1K105

题解

这个有ABC三个种类,所以我们想要开 3 ∗ n 3*n 3n 的空间。
我们可以令 1 ∗ n 1*n 1n 空间为本, 2 ∗ n 2*n 2n 空间为食物(被吃), 3 ∗ n 3*n 3n 空间为天敌(吃他的)
所以对于x来说。
[x]所在集合就是x的同类
[x+n]所在集合就是x的食物
[x+2*n] 所在集合就是x的天敌。

操作来说
如果 x x x y y y 那么

  • x 的食物是 y
  • x 的天敌是 y 的食物
  • y 的天敌是 x

如果 x x x y y y 的同类,那么

  • x 的食物不是 y
  • x 的天敌也不是 y

java实现代码

package com.yu;import java.io.*;
import java.util.stream.IntStream;public class Main {static final StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));public static int nextInt() throws IOException {st.nextToken();return (int) st.nval;}public static int[] a;public static int find(int i) {if (a[i] == i) return i;else return a[i] = find(a[i]);}public static void union(int i, int j) {int x = find(i);int y = find(j);if (x != y) a[x] = y;}public static void main(String[] args) throws IOException {int n = nextInt();int k = nextInt();a = IntStream.range(0, n * 3 + 3).toArray();int ans = 0;for (int i = 0; i < k; i++) {int j = nextInt();int x = nextInt();int y = nextInt();if (x > n || y > n) {ans++;continue;}if (j == 1) {if (find(x) == find(y + n) || find(x) == find(y + 2 * n)) ans++;else {union(x, y);union(x + n, y + n);union(x + 2 * n, y + 2 * n);}} else {if (find(x) == find(y) || find(x) == find(y + n) || x == y) ans++;else {union(x, y + 2 * n);union(x + n, y);union(y + n, x + 2 * n);}}}System.out.println(ans);}
}

http://www.ppmy.cn/news/102119.html

相关文章

终极AI工具包--不用到处找资料了

终极AI工具包 学习 第1章&#xff1a;如何学习ChatGPT&#xff08;基础知识&#xff09; 1、什么是ChatGPT2、ChatGPT简介&#xff1a;基础知识3、什么是ChatGPT以及如何使用它 第2章&#xff1a;如何学习ChatGPT&#xff08;高级&#xff09; 从零开始到精通ChatGPT 第3…

Qt Quick系列(3)—组件component

&#x1f680;作者&#xff1a;CAccept &#x1f382;专栏&#xff1a;Qt Quick 文章目录 概念相关知识点代码示例总结 概念 在Qt Quick中&#xff0c;组件&#xff08;Component&#xff09;是一种可重用的元素&#xff0c;可以包含其他子组件或属性。它们可以用来创建自定…

spring boot 单元测试JUnit5使用Mockito模拟Mock数据调用

spring boot 单元测试JUnit5使用Mockito模拟Mock数据调用 好大一批新用法&#xff0c;大家静下心来好好看看吧 文章目录 spring boot 单元测试JUnit5使用Mockito模拟Mock数据调用1. spring boot 使用 Mockito.when().thenReturn()模拟返回值1&#xff09;测试mockito.when设置固…

银行面试遭遇两难情景题如何回答(下)

银行面试形式离不开自我介绍半结构化无领导群面、辩论赛等形式。遇到两难性问题&#xff0c;很多考生都不知道该如何作答&#xff0c;按照常规思维很容易给自己挖坑。今天就接着来说说遇到这类题如何回答&#xff1f;从如信银行考试中心了解到&#xff1a; 一、根据社会价值观进…

计算机网络第一章——计算机体系结构(上)

提示&#xff1a;剑未佩妥&#xff0c;出门已是江湖&#xff1b;酒尚余温&#xff0c;入口不识乾坤&#xff0c;愿历尽千帆&#xff0c;归来仍是少年。 文章目录 1.1.1 概念和功能计算机网络的概念计算机网络的功能计算机网络的发展——第一阶段第二阶段——三级结构第三阶段—…

北醒Modbus协议在Python下Tkinter模块实现功能配置的GUI设计

目录 实验目的测试环境Python库需求Benewake(北醒) TF雷达接线示意图库安装说明例程运行展示 实验目的 实现485接口系列雷达Modbus协议在Python下Tkinter模块实现功能配置的GUI设计。 本例程主要功能如下&#xff1a; 1.设备连接&#xff08;已知雷达设备的波特率和站号&#…

类实例化和实例初始化

就算不写main方法里面的3句&#xff0c;也会执行5 1 10 6 因为main方法所在的类需要先加载和初始化 执行顺序如下&#xff1a;先初始化父类再初始化子类 静态实例变量显示赋值和静态代码块代码从上到下顺序执行&#xff08;根据书写顺序&#xff09; 子类的实例化方法&am…

MT6765 处理器参数 MTK6765芯片性能配置|详细参数

MT6765处理器&#xff0c;也被称为Helio P35&#xff0c;是联发科(MediaTek)推出的高性能智能芯片。作为目前市场上受欢迎的低成本智能芯片之一&#xff0c;MT6765以其卓越的性能和创新技术为用户提供了更加顺畅和高效的使用体验。 MT6765作为一款八核芯片&#xff0c;MT6765的…