코딩테스트
백준 14595 동방탈출 c++ (분리 집합 응용)
코앤미
2022. 8. 15. 18:57
분리집합 응용문제를 하나 들고 왔습니다. 분리집합에 관한 기본적인 지식은 생략하고
해당 문제의 핵심 아이디어만 아래 코드블럭의 주석에 구체적이게 달아 놓았으니 참고하세요!
#include<iostream>
using namespace std;
#include<stdio.h>
int n, m,cnt;
int arr[1000000];
int find(int a) {
if (arr[a] == a)
return a;
else
return arr[a] = find(arr[a]);
}
void join(int a, int b) {
a = find(a);
b = find(b);
if (a == b)return;
arr[a] = b; //두번째 파라미터가 첫번째 파라미터의 부모가 된다.
}
int main() {
scanf("%d %d", &n, &m);
cnt = n;
for (int i = 1; i <= n; i++) {
arr[i] = i;
}
int x, y;
for (int i = 0; i < m; i++) {
scanf("%d %d", &x, &y);
x--,y--;
while (find(x) != find(y)) {//x~y 범위 모든 원소를 join 연산시 시간초과.
--cnt;// 서로 다른 두 그룹을 합칠때마다 그룹의 개수가 1개씩 줄어든다.
int nxt = find(x) + 1;
//root 가 가장 큰 수가 되게 ( 가장 오른쪽) 설정해보자.
// (1 2 3) (4) (5) 의 경우 3이 root >> 이후엔 find(x)+1 로 바로 옆 덩어리로 이동 가능!
// find(x) 시 3 나옴 >> 3+1 4 >> x~y 범위 안에서 연결되있지 않은 덩어리를 O(1)으로 찾기 가능.
join(x, y); // x<y 인데 join 코드는 두번째 파라미터가 부모가 되게 구현함.
x = nxt;
}
}
printf("%d\n", cnt);
}