티스토리 뷰
1717번: 집합의 표현
첫째 줄에 n(1 ≤ n ≤ 1,000,000), m(1 ≤ m ≤ 100,000)이 주어진다. m은 입력으로 주어지는 연산의 개수이다. 다음 m개의 줄에는 각각의 연산이 주어진다. 합집합은 0 a b의 형태로 입력이 주어진다. 이는
www.acmicpc.net
이 문제는 유니온 파인드라는 알고리즘을 이용하여 합집합을 만들고, 판단하는 문제이다.
자료구조를 코드로 만들어 표현하는 부분을 더 연습해야겠다고 생각했다!
유니온 파인드(Union-Find) 알고리즘이란?
- 그래프 알고리즘 중 하나이다. 분리 집합, 합집합 찾기의 의미를 갖는다.
- parent [] 배열로 각 노드가 어떤 부모 노드 아래에 있는지 그래프로 만든다.
x | 1 | 2 | 3 |
parent[x] | 1 | 2 | 3 |
-> 초기 parent[] 배열은 노드마다 분리되어 있으므로 자신의 노드 번호를 가진다.
for(int i=0;i<=n;i++) {
parent[i]=i;
}
- 2가지 연산으로 이루어진다.
-> 1. find(x) : x가 어떤 집합에 속해있는지 찾는다.
- 가장 상위의 노드 x의 경우 x == parent [x] 관계가 성립한다.
- 따라서 재귀를 통해 집합의 가장 상위 노드를 찾아 return 한다.
static int find(int x) {
if(x == parent[x])
return x;
else
return parent[x] = find(parent[x]);
}
-> 2. union(x, y) : x와 y가 포함된 집합을 합친다.
- 집합의 가장 상위 노드로 같은 집합임을 나타내게 되는데, 숫자가 작은 노드를 상위 노드로 선택하여 진행(반대도 o)
- 이미 같은 집합이라면 parent [x]==parent [y] 이므로 갱신이 필요치 않음
static void union(int x, int y) {
x = find(x);
y = find(y);
if(x!=y) {
if(x < y) parent[y] = x;
else parent[x] = y;
}
}
+ 같은 parent[]값을 갖는지 즉, 같은 집합인지 판단
- find()를 재귀로 관계를 타고 들어가게 됨.
static boolean isSameParent(int x, int y) {
x = find(x);
y = find(y);
if(x == y)
return true;
else
return false;
}
그래프와 표로 알아보기
1. {1} , {2,3}의 집합인 상태
x | 1 | 2 | 3 |
parent[x] | 1 | 2 | 2 |
2. 두 집합을 연결, -> union(1,3)을 수행
- parent [3]인 2번의 노드의 값이 1로 경신된다.
x | 1 | 2 | 3 |
parent[x] | 1 | 1 | 2 |
3. 1과 3이 같은 집합인지 확인 -> isSameParent(1,3)
- find() 재귀를 통해 parent [1] == parent [3]인지 확인하게 됨.
- 가장 숫자가 작은 노드 1번을 parent [] 값으로 모두 갖게 되어 하나의 합집합인 것을 알 수 있다.
x | 1 | 2 | 3 |
parent[x] | 1 | 1 | 1 |
문제풀이
-uinon-find를 사용하여 합집합의 관계를 형성한다.
-같은 집합에 속해 있다면 -> find(x) == find(y) => parent [x] == parent [y] YES 아니면 NO를 출력.
public class Ex_1717 {
static int[] parent;
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
parent = new int[n+1];
for(int i=0;i<=n;i++) {
parent[i]=i;
}
while(m-- > 0) {
st = new StringTokenizer(br.readLine());
int type = Integer.parseInt(st.nextToken());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
if(type==0)
union(a,b);
else
bw.append(isSameParent(a, b) ? "YES\n" : "NO\n");
}
bw.flush();
}
static void union(int x, int y) {
x = find(x);
y = find(y);
if(x!=y) {
if(x < y) parent[y] = x;
else parent[x] = y;
}
}
static int find(int x) {
if(x == parent[x])
return x;
else
return parent[x] = find(parent[x]);
}
static boolean isSameParent(int x, int y) {
x = find(x);
y = find(y);
if(x == y)
return true;
else
return false;
}
}
무언가 잘못된 것이 있다면 댓글로 달아주세요!
'CS공부 > 알고리즘&문제풀이' 카테고리의 다른 글
[알고리즘] 최소 스패닝 트리(MST) - 크루스칼, 프림 (0) | 2021.05.21 |
---|---|
[백준 1992] 네트워크 연결(java)-최소 스패닝 트리(MST) (0) | 2021.05.18 |
[백준 1991] 트리순회(java) - 전위,중위,후위 순회 (0) | 2021.04.28 |
[백준 17136] 색종이 붙이기(java) (0) | 2021.04.15 |
[프로그래머스]2017카카오코드 본선 : 단체사진 찍기(java) (0) | 2021.02.18 |
- Total
- Today
- Yesterday
- Oracle
- JavaScript
- OS
- Spring
- 채팅
- 삼성 sw역량테스트
- programers
- DP
- 완전탐색
- 알고리즘
- 분리 집합
- 프로그래머스
- dfs
- Stomp
- 최소 스패닝 트리
- 백준
- 자바
- Baekjoon
- sockjs
- SWEA
- git
- BFS
- 정렬
- MST
- 삼성 sw역량 테스트
- 코딩테스트
- Heap
- 운영체제
- websocket
- java
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |