집합의 표현
https://www.acmicpc.net/problem/1717
시간 제한 | 메모리 제한 | 제출 | 정답 | 맞힌 사람 | 정답 비율 |
---|---|---|---|---|---|
2 초 | 128 MB | 75296 | 23857 | 14435 | 28.135% |
문제
초기에 n+1개의 집합 {0}, {1}, {2}, … , {n}이 있다.
여기에 합집합 연산과, 두 원소가 같은 집합에 포함되어 있는지를 확인하는 연산을 수행하려고 한다.
집합을 표현하는 프로그램을 작성하시오.
입력
첫째 줄에 n, m이 주어진다.
m은 입력으로 주어지는 연산의 개수이다.
다음 m개의 줄에는 각각의 연산이 주어진다.
합집합은 0 a b의 형태로 입력이 주어진다.
이는 a가 포함되어 있는 집합과, b가 포함되어 있는 집합을 합친다는 의미이다.
두 원소가 같은 집합에 포함되어 있는지를 확인하는 연산은 1 a b의 형태로 입력이 주어진다.
이는 a와 b가 같은 집합에 포함되어 있는 지를 확인하는 연산이다.
출력
1로 시작하는 입력에 대해서 a와 b가 같은 집합에 포함되어 있으면 “YES
” 또는 “yes
“를,
그렇지 않다면 “NO
” 또는 “no
“를 한 줄에 하나씩 출력한다.
제한
- 1 ≤ n ≤ 1,000,000
- 1 ≤ m ≤ 100,000
- 0 ≤ a, b ≤ n
- a, b는 정수
- a와 b는 같을 수도 있다.
예제 입력 1
7 8 0 1 3 1 1 7 0 7 6 1 7 1 0 3 7 0 4 2 0 1 1 1 1 1
예제 출력 1
NO NO YES
출처
- 잘못된 데이터를 찾은 사람: Apple_Cplus
- 문제를 번역한 사람: author5
- 데이터를 추가한 사람: njw1204
알고리즘 분류
접근 방법
통과된 코드
#include <iostream> using namespace std; constexpr int Max = 1000001; // 유니온 root노드 배열 int uArr[Max]; int N, M, u, b, c; //부모를 찾는 함수 //모든 경로가 부모를 가르키게 함 //상수 시간의 복잡도 int Find(int x) { if (uArr[x] == x) return x; return uArr[x] = Find(uArr[x]); } //두 노드를 연결 시키는 것 //기준을 정해서 연결시키는 것이 헷갈리지 않음 //작은쪽이 부모 or 큰쪽이 부모 void Union(int x, int y) { x = Find(x); y = Find(y); if (x != y) { if (x < y) uArr[y] = x; else uArr[x] = y; } } int main() { ios_base::sync_with_stdio(false); // scanf와 동기화를 비활성화 // cin.tie(null); 코드는 cin과 cout의 묶음을 풀어줍니다. cin.tie(NULL); cout.tie(NULL); cin >> N >> M; // 유니온 배열 초기화 for (int i = 0; i <= N; i++) uArr[i] = i; for (int i = 0; i < M; i++) { cin >> u >> b >> c; if (u == 0) { // 합집합 연산 Union(b, c); } else { // 질의 if (Find(b) != Find(c)) cout << "NO\n"; else cout << "YES\n"; } } return 0; }
핑백: 알고리즘 – 유니온 파인드(Union find) & 서로소 집합(Disjoint Set) - 어제와 내일의 나 그 사이의 이야기