import java.util.Scanner;
public class Main {
public static int T; // 테스트 케이스 개수
public static int n, m; // 나라 n개, 비행기 m
public static int[] parent = new int[1000001]; // 부모 테이블 초기화하기
public static int result = 0;
// 특정 원소가 속한 집합을 찾기
public static int findParent(int x) {
// 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
if (x == parent[x]) return x;
return parent[x] = findParent(parent[x]);
}
// 두 원소가 속한 집합을 합치기
public static void unionParent(int a, int b) {
a = findParent(a);
b = findParent(b);
if (a < b) parent[b] = a;
else parent[a] = b;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
T = sc.nextInt();
for (int t = 0; t < T; t++) {
result = 0;
n = sc.nextInt();
m = sc.nextInt();
// 부모 테이블상에서, 부모를 자기 자신으로 초기화
for (int i = 1; i <= n; i++) {
parent[i] = i;
}
for (int i = 0; i < m; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
if (findParent(a) != findParent(b)) {
unionParent(a, b);
result++;
}
}
System.out.println(result);
}
}
}
상근이가 n개국을 여행할 때 m개의 비행기를 타고 이동해야하는데 가장 적은 비행기를 타야하니까 최소 간선의 개수를 구하면 된다.
가장 적은 종류의 비행기 == 최소 간선의 개수
1. 크루스칼 알고리즘으로 최소 신장 트리를 구한다.
2. 최소 신장 트리에 구성되어있는 간선의 개수가 최소 간선의 개수가 됨
T개의 테스트 개수만큼 반복해서 나라의 개수 n, 비행기의 개수 m을 구한다.
m번 a, b 쌍들을 입력 (a,b를 왕복하는 비행기)
a, b가 같은 집합에 속해있지 않을 때, 유니온 연산 실행(합집합을 만드는 연산) > 간선의 수 카운트 +1
만약 a, b가 같은 집합에 속해있다면, 유니온 연산을 실행하지 않음 -> 이미 이어지는 간선이 있다는 의미임 == 이어지는 비행기가 없어도 이동가능하다는 뜻 !
유니온 연산을 실행하는 것은 a, b가 이어지는 간선이 만들어진다는 의미이므로 비행기 종류의 최소 개수에 +1을 더함.
모든 연산이 끝나면 result 변수에 최소 간선의 수가 들어있게 된다.
'코테 > 백준' 카테고리의 다른 글
백준 2018번: 수들의 합 5 - Java (0) | 2024.06.26 |
---|---|
백준 1647: 도시 분할 계획 - Java (0) | 2024.06.26 |
백준 1717번: 집합의 표현 - Java (0) | 2024.06.26 |
백준 1541 잃어버린 괄호 - 파이썬 (0) | 2024.06.25 |
백준 10816 숫자 카드 2 - 파이썬 (0) | 2024.06.25 |