L2-4 部落 (25分)

在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈。我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同一个部落。

输入格式:

输入在第一行给出一个正整数NNN≤104\le 10^4104),是已知小圈子的个数。随后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^4104),是查询次数。随后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;
	}
}



发布了45 篇原创文章 · 获赞 8 · 访问量 1762

猜你喜欢

转载自blog.csdn.net/weixin_43888039/article/details/104115673