유니온 파인드 예제 - 2
문제 분석
도시의 연결 유무를 유니온 파인드 연산을 이용해 해결할 수 있다는 아이디어를 떠올릴 수 있으면 쉽게 해결할 수 있는 문제다.
일반적으로 유니온 파인드는 그래프 영역에서 많이 활용되지만, 이 문제처럼 단독으로도 활용할 수 있다.
문제에서 도시 간 연결 데이터를 인접 행렬의 형태로 주었기 때문에 인접 행렬을 탐색하면서 연결될 때마다
union연산을 수행하는 방식으로 문제에 접근하면 된다.
손으로 풀어보기
도시와 여행 경로 데이터를 저장하고, 각 노드와 관련된 대표 노드 리스트의 값을 초기화한다.
도시 연결 정보가 저장된 인접 행렬을 탐색하면서 도시가 연결돼 있을 때
union연산을 수행한다.여행 경로에 포함된 도시의 대표 노드가 모두 같은지 확인한 후 결과를 출력한다.
슈도코드
n(도시의 수) m(여행 계획에 속한 도시의 수)
city(도시 연결 인접 행렬)
find(a):
a가 대표 노드면 a 리턴
아니면 a의 대표 노드 값을 find(parent[a])값으로 저장(재귀 형태)
union(a, b):
a와 b의 대표 노드 찾기
두 원소의 대표 노드끼리 연결
for i 1~n+1 반복:
city 데이터 저장
route(여행 계획 도시 저장 리스트)
parent(대표 노드 저장 리스트)
for n 반복:
parent 대표 노드 자기 자신으로 초기화
for i n 반복:
for j n 반복:
if city[i][j]가 1이면:
union(i, j)
isConnect(연결 여부 변수)
for 2~m 반복:
route에 포함되는 노드들의 대표 노드가 모두 동일한지 확인한 후 isConnect 저장
isConnect 값에 따라 YES 또는 NO 출력코드 구현 - 파이썬
n = int(input())
m = int(input())
city = [[0 for _ in range(n + 1)] for _ in range(n + 1)]
for i in range(1, n + 1):
city[i][1:] = list(map(int, input().split()))
route = list(map(int, input().split()))
parent = [0] * (n + 1)
for i in range(1, n + 1):
parent[i] = i
def find(a):
if a == parent[a]:
return a
else:
parent[a] = find(parent[a])
return parent[a]
def union(a, b):
a = find(a)
b = find(b)
if a != b:
parent[b] = a
for i in range(1, n + 1):
for j in range(1, n + 1):
if city[i][j] == 1: # 두 도시가 연결되어 있다면 union 수행
union(i, j)
index = find(route[0])
isConnect = True
for i in range(1, m):
if index != find(route[i]):
isConnect = False
break
if isConnect:
print("YES")
else:
print("NO")코드 구현 - 자바
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int[] parent;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int n = Integer.parseInt(br.readLine());
int m = Integer.parseInt(br.readLine());
parent = new int[n + 1];
for (int i = 1; i <= n; i++) {
parent[i] = i;
}
int[][] city = new int[n][n];
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < n; j++) {
city[i][j] = Integer.parseInt(st.nextToken());
if (city[i][j] == 1) {
union(i + 1, j + 1);
}
}
}
int[] route = Arrays.stream(br.readLine().split(" "))
.mapToInt(Integer::parseInt)
.toArray();
boolean isConnect = true;
int index = find(route[0]);
for (int i = 1; i < m; i++) {
if (index != find(route[i])) {
isConnect = false;
break;
}
}
System.out.println(isConnect ? "YES" : "NO");
}
private static int find(int a) {
if (a == parent[a]) {
return a;
} else {
parent[a] = find(parent[a]);
return parent[a];
}
}
private static void union(int a, int b) {
a = find(a);
b = find(b);
if (a != b) {
parent[b] = a;
}
}
}Last updated