题目背景
若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。
题目描述
规定:x 和 y 是亲戚,y 和 z 是亲戚,那么 x 和 z 也是亲戚。如果 x,y 是亲戚,那么 x 的亲戚都是 y 的亲戚,y 的亲戚也都是 x 的亲戚。
输入格式
第一行:三个整数n,m,p(n,m,p≤5000),分别表示有n个人,m个亲戚关系,询问p对亲戚关系。
以下 m 行:每行两个数 Mi,Mj,1 ≤ Mi, Mj ≤ N,表示 Mi 和 Mj 具有亲戚关系。
接下来 p 行:每行两个数 Pi,Pj,询问 Pi 和 Pj 是否具有亲戚关系。
输出格式
p 行,每行一个 Yes 或 No。表示第 i 个询问的答案为“具有”或“不具有”亲戚关系。
输入输出样例
输入 #1
6 5 3 1 2 1 5 3 4 5 2 1 3 1 4 2 3 5 6
输出 #1
Yes Yes No
解题思路
- 题目大意:给定n个人,再给出m组亲戚关系,最后询问q次它们是否问亲戚关系,是的就输出Yes否则就输出No
- 这道题是比较经典的并查集,如果您还不知道并采集的话,我在这里推荐一个博主写的一篇关于并查集文章,链接就放这了:http://t.csdn.cn/fyzqw
- 我就不解释并查集是用来干嘛的,它有什么用,用在哪些地方,我推荐的这篇文章还是比较容易理解的,思路也很清晰。
- 接下来就是并查集的基本操作了,下面就附上代码,代码中有详细的注解。
代码
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main{
static class Input { // 优化输入
BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(is);
public int nextInt() throws IOException {
in.nextToken();
return (int) in.nval;
}
}
static int rest[]; // 并采集数组
static int n, m, p; // n:表示有多少人 m:表示有几组关系 p:表示询问关系次数
public static void main(String[] args) throws IOException {
Input in = new Input();
PrintWriter pr = new PrintWriter(new BufferedOutputStream(System.out));// 优化输出
n = in.nextInt();
m = in.nextInt();
p = in.nextInt();
init();
for (int i = 0; i < m; i++) {
int x = in.nextInt();
int y = in.nextInt();
if (find(x) != find(y)) // 如果它们的根不同就和合并组成亲戚关系
union(x, y);
}
for (int i = 0; i < p; i++) {
int x = in.nextInt();
int y = in.nextInt();
if (find(x) == find(y)) // 如果是亲戚(判断它们的根是否一样)就输出Yes.
pr.println("Yes");
else
pr.println("No"); // 否则就输出No
}
pr.flush();
}
public static void union(int x, int y) { // 合并
int xRoot = find(x);
int yRoot = find(y);
if (xRoot != yRoot)
rest[xRoot] = yRoot;
}
public static int find(int q) { // 查找
if (q == rest[q])
return q;
return rest[q] = find(rest[q]); // 路径压缩
}
public static void init() { // 初始化并采集数组
rest = new int[n + 1];
for (int i = 1; i <= n; i++) // 开始让它们亲戚关系都指向自己(因为开始它们都没有亲戚)
rest[i] = i;
}
}
总结:这道题没有设什么坑,就是一道裸的并查集,如果您什么不懂或比较疑惑地方欢迎在评论区留言~
525

被折叠的 条评论
为什么被折叠?



