문제해결/SWExpertAcademy

SWExpertAcademy 7465-창용 마을 무리의 개수(JAVA)

mangzz 2021. 8. 24. 20:20

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWngfZVa9XwDFAQU 

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

창용 마을에는 N명의 사람이 살고 있다.

사람은 편의상 1번부터 N번 사람까지 번호가 붙어져 있다고 가정한다.

두 사람은 서로를 알고 있는 관계일 수 있고, 아닐 수 있다.

두 사람이 서로 아는 관계이거나 몇 사람을 거쳐서 알 수 있는 관계라면,

이러한 사람들을 모두 다 묶어서 하나의 무리라고 한다.

창용 마을에 몇 개의 무리가 존재하는지 계산하는 프로그램을 작성하라.


[입력]

첫 번째 줄에 테스트 케이스의 수 T가 주어진다.

각 테스트 케이스의 첫 번째 줄에는 각각 창용 마을에 사는 사람의 수와 서로를 알고 있는 사람의 관계 수를 나타내는

두 정수 N, M(1 ≤ N ≤ 100, 0 ≤ M ≤ N(N-1)/2) 이 공백 하나로 구분되어 주어진다.

이후 M개의 줄에 걸쳐서 서로를 알고 있는 두 사람의 번호가 주어진다.

같은 관계는 반복해서 주어지지 않는다.


[출력]

각 테스트 케이스마다 ‘#x’(x는 테스트케이스 번호를 의미하며 1부터 시작한다)를 출력하고,

무리의 개수를 출력한다.

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.StringTokenizer;

public class Solution1 {
	static int N; // 원소갯수
	static int[] parents;// 부모원소 관리
	static int cnt;

	// 모든 원소를 자신의 대표자로 만듦
	private static void make() {
		parents = new int[N+1];
		for (int i = 1; i <= N; i++) {
			parents[i] = i;
		}
	}

	// a가 속한 집합의 대표자 찾기
	private static int find(int a) {
		if (a == parents[a])
			return a;
		return parents[a] = find(parents[a]);
	}

	private static boolean union(int a, int b) {
		int aRoot = find(a);
		int bRoot = find(b);
		// 이미 같은 집합이면 union 하지 않음
		if (aRoot == bRoot)
			return false;
		// 같은 집합이 아니라면 합치기
		parents[bRoot] = parents[aRoot];
		return true;
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		StringBuilder sb = new StringBuilder();
		int TC = Integer.parseInt(br.readLine());
		for (int t = 1; t <= TC; t++) {
			sb.append("#" + t + " ");
			st = new StringTokenizer(br.readLine(), " ");
			N = Integer.parseInt(st.nextToken());
			int M = Integer.parseInt(st.nextToken());
			
			//합집합 연산하기 
			make();
			for (int i = 0; i < M; i++) {
				st = new StringTokenizer(br.readLine(), " ");
				int a = Integer.parseInt(st.nextToken());
				int b = Integer.parseInt(st.nextToken());
				union(a,b);
			}
			
			//자신이 속한 집합의 대표자 찾기
			for(int i = 1; i <= N; i++) {
				find(i);
			}
			
			//hashset에 대표자를 넣어 중복이 제거된 대표자들의 수 =그룹 수 
			HashSet<Integer> hset = new HashSet<>();
			for (int temp = 1; temp <=N; temp++) {
				hset.add(parents[temp]);
			}
			sb.append(hset.size()+"\n");
		}
		System.out.println(sb);
	}
}

합집합 연산 후 자신이 속한 집합의 진짜 대표자를 찾아 parents를 바꿔준 뒤,

hashset에 parents의 원소 값들을 넣어주면 중복이 제거된 대표자들을 얻을 수 있습니다.

중복이 제거된 대표자들의 수 = 그룹 수 이므로 hset.size를 출력해주었습니다.