일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 |
Tags
- 백준
- 페이코 추천인
- programmers
- 배열
- 페이코 추천인코드
- Java
- 한정 분기
- php 프로그래밍 입문 연습문제
- 파이썬
- C
- spring
- SWEA
- php 프로그래밍 입문 솔루션
- 스프링
- JAVA SPRING
- 최단 경로
- php 프로그래밍 입문 예제
- 플러터
- php
- 자바 스프링
- 자바
- php 프로그래밍 입문 3판
- C언어
- 페이코 초대코드
- php 프로그래밍 입문
- php 프로그래밍 입문 문제풀이
- 페이코 친구코드
- 플러터 개발환경 설정
- php 프로그래밍
- Flutter
Archives
- Today
- Total
11-07 11:40
ImJay
[SWEA/Java] 3289. 서로소 집합 본문
반응형
[SWEA/Java] 3289. 서로소 집합
문제 해석
서로소 집합 문제는 주어진 집합에 대해 특정 연산(합집합, 소속 확인)을 수행하는 알고리즘을 구현하는 문제다. 이 문제에서는 두 가지 연산을 지원해야 한다:
- 두 원소가 포함된 집합을 합친다.
- 두 원소가 같은 집합에 속하는지 확인한다.
풀이 과정
- union-find 자료구조를 사용하여 각 원소의 대표자와 집합의 높이를 관리한다.
- 초기화에서는 각 원소가 자신만을 포함하는 집합의 대표자가 되도록 설정한다.
- 합집합(union) 연산은 두 원소의 대표자를 찾아, 하나의 대표자 아래에 다른 대표자를 통합하는 방식으로 진행한다. 높이가 낮은 집합을 높이가 높은 집합 아래에 통합하고, 높이가 같을 경우 한쪽의 높이를 증가시킨다.
- 소속 확인(find) 연산은 원소의 최종 대표자를 찾는다. 이 과정에서 경로 압축을 통해 집합의 구조를 최적화한다.
코드
package edu.ssafy.im.SWEA.D4.No3289;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
public class Solution {
public static void main(String[] args) throws NumberFormatException, IOException {
new Solution().io();
}
private int n; // 집합의 원소 수
private int m; // 수행할 연산의 수
private int[] set; // 각 원소의 대표자
private int[] height; // 각 집합의 높이
private StringBuilder sb = new StringBuilder(); // 결과 문자열을 저장하는 StringBuilder
private void io() throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int T = Integer.parseInt(br.readLine()); // 테스트 케이스 수
for (int t = 1; t <= T; t++) {
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
makeSet(); // 초기 집합 생성
sb.append("#").append(t).append(" ");
for (int i = 0; i < m; i++) {
st = new StringTokenizer(br.readLine());
int c = Integer.parseInt(st.nextToken()); // 연산 종류
int a = Integer.parseInt(st.nextToken()) - 1; // 원소 1
int b = Integer.parseInt(st.nextToken()) - 1; // 원소 2
doCommand(c, a, b); // 연산 수행
}
sb.append("\n");
}
bw.write(sb.toString());
bw.flush();
bw.close();
}
private void makeSet() { // 각 원소를 자기 자신의 대표자로 초기화
set = new int[n];
height = new int[n];
for (int i = 0; i < n; i++) {
set[i] = i;
height[i] = 0;
}
}
private void doCommand(int c, int a, int b) { // 주어진 연산 수행
switch (c) {
case 0: // union 연산
unionSet(a, b);
break;
case 1: // find 연산
if(findSet(a) == findSet(b)) {
sb.append(1);
} else {
sb.append(0);
}
break;
}
}
private int findSet(int org) { // 경로 압축을 사용한 find 연산
if (set[org] == org) return org;
else return set[org] = findSet(set[org]);
}
private void unionSet(int a, int b) { // 높이를 사용한 union 연산
int rootA = findSet(a);
int rootB = findSet(b);
if(rootA != rootB) {
if(height[rootA] > height[rootB]) {
set[rootB] = rootA;
} else {
set[rootA] = rootB;
if(height[rootA] == height[rootB]) height[rootB]++;
}
}
}
}
시간 복잡도 분석
union-find 알고리즘은 경로 압축과 함께 사용할 때 거의 상수 시간에 가까운 find 연산을 제공한다. union 연산도 find 연산을 기반으로 하므로, 각 연산의 평균적인 시간 복잡도는 거의 상수 시간이다. 따라서 전체 시간 복잡도는 주어진 연산 수 에 비례하며, 이다.
느낀점
서로소 집합 자료구조는 그래프 알고리즘뿐만 아니라 다양한 알고리즘 문제에서 중요하게 사용되는 기본적인 자료구조 중 하나다. 이 문제를 통해 union-find 구조를 효과적으로 구현하고 활용하는 방법을 더 잘 이해할 수 있었다.
반응형
'SW Expert Academy > D4' 카테고리의 다른 글
[SWEA/Java] 1251. 하나로 (0) | 2024.04.21 |
---|---|
[SWEA/Java] 7465. 창용 마을 무리의 개수 (1) | 2024.04.19 |
[SWEA/Java] 7208. 지도 칠하기 (1) | 2024.04.19 |
[SWEA/Java] 7733. 치즈 도둑 (0) | 2024.04.17 |
[SWEA/Java] 7699. 수지의 수지 맞는 여행 (0) | 2024.04.17 |
Comments