在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈。我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同一个部落。
输入格式:
输入在第一行给出一个正整数NNN(≤104\le 10^4≤104),是已知小圈子的个数。随后NNN行,每行按下列格式给出一个小圈子里的人:
KKK P[1]P[1]P[1] P[2]P[2]P[2] ⋯\cdots⋯ P[K]P[K]P[K]
其中KKK是小圈子里的人数,P[i]P[i]P[i](i=1,⋯,Ki=1, \cdots , Ki=1,⋯,K)是小圈子里每个人的编号。这里所有人的编号从1开始连续编号,最大编号不会超过10410^4104。
之后一行给出一个非负整数QQQ(≤104\le 10^4≤104),是查询次数。随后QQQ行,每行给出一对被查询的人的编号。
输出格式:
首先在一行中输出这个社区的总人数、以及互不相交的部落的个数。随后对每一次查询,如果他们属于同一个部落,则在一行中输出Y
,否则输出N
。
输入样例:
4
3 10 1 2
2 3 4
4 1 5 7 8
3 9 6 4
2
10 5
3 7
输出样例:
10 2
Y
N
两个测试点超时
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
//** Class for buffered reading int and double values *//*
class Reader {
static BufferedReader reader;
static StringTokenizer tokenizer;
// ** call this method to initialize reader for InputStream *//*
static void init(InputStream input) {
reader = new BufferedReader(new InputStreamReader(input));
tokenizer = new StringTokenizer("");
}
// ** get next word *//*
static String next() throws IOException {
while (!tokenizer.hasMoreTokens()) {
// TODO add check for eof if necessary
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
static boolean hasNext()throws IOException {
return tokenizer.hasMoreTokens();
}
static String nextLine() throws IOException{
return reader.readLine();
}
static char nextChar() throws IOException{
return next().charAt(0);
}
static int nextInt() throws IOException {
return Integer.parseInt(next());
}
static float nextFloat() throws IOException {
return Float.parseFloat(next());
}
}
public class Main {
private static int[]a;
public static void main(String[] args) throws IOException {
Reader.init(System.in);
int n = Reader.nextInt();
Set<Integer>set = new HashSet<Integer>();
a = new int[10001];
for (int i = 1; i < a.length; i++) {
a[i] = i;
}
input(n,set);
int q = Reader.nextInt();
int cnt = 0;
for (int i = 1; i <= set.size(); i++) {
if(a[i]==i)cnt++;
}
System.out.println(set.size()+" "+cnt);
for (int i = 0; i < q; i++) {
int node1 = Reader.nextInt();
int node2= Reader.nextInt();
if (find(node1)==find(node2)) {
System.out.println("Y");
}else {
System.out.println("N");
}
}
}
static void input(int n, Set<Integer> set) throws IOException {
for (int i = 0; i < n; i++) {
int k = Reader.nextInt();
int a = Reader.nextInt();
set.add(a);
for (int j = 1; j < k; j++) {
int b = Reader.nextInt();
set.add(b);
join(a,b);
}
}
}
static int find(int x) // 查找根节点
{
int r = x;
while (a[r] != r) // 返回根节点 r
r = a[r];
int i = x, j;
while (i != r) // 路径压缩
{
j = a[i]; // 在改变上级之前用临时变量 j 记录下他的值
a[i] = r; // 把上级改为根节点
i = j;
}
return r;
}
static void join(int x, int y) // 判断x y是否连通,
// 如果已经连通,就不用管了 如果不连通,就把它们所在的连通分支合并起,
{
int fx = find(x), fy = find(y);
if (fx != fy)
a[fx] = fy;
}
}