dev_beomgeun
꾸준하게 차근차근
dev_beomgeun
전체 방문자
오늘
어제
  • 분류 전체보기 (170)
    • 전공 (0)
      • 운영체제 (0)
      • 알고리즘 (0)
      • 자료구조 (0)
      • 데이터베이스 (0)
      • 네트워크 (0)
    • 개발 공부 (32)
      • 웹 (6)
      • 리눅스 (4)
      • 머신러닝 (1)
      • 스프링 (17)
      • Git (2)
      • AWS (2)
    • 개발 도서, 강의 (3)
      • 스프링 입문을 위한 자바 객체지향의 원리와 이해 (0)
      • 모든 개발자를 위한 HTTP 웹 기본 지식(김영한.. (2)
      • 스프링 부트와 AWS로 혼자 구현하는 웹서비스 (1)
    • 문제 풀이 (118)
      • 백준 알고리즘 (72)
      • 프로그래머스 알고리즘, SQL (38)
      • Hackerrank SQL (8)
    • 프로젝트 기록 (4)
      • 캡스톤 종합설계 (4)
      • 반려하루 프로젝트 (0)
    • 활동 기록 (12)
      • 네이버 부스트캠프 (7)
      • 취준 & 코테 (4)
      • 소프트웨어 마에스트로 13기 (1)
    • 이것저것 (1)

블로그 메뉴

  • 홈
  • 깃허브
  • 링크드인
  • 방명록

공지사항

인기 글

태그

  • 스프링
  • BFS
  • 서블릿
  • 프로그래머스 SQL
  • AI Tech
  • 그래프탐색
  • 백준 DP
  • Baekjoon
  • 네이버 부스트캠프
  • 기록
  • 백준
  • 반성
  • 부스트캠프
  • 일기
  • Hackerrank
  • c++
  • 회고
  • HackerRank mysql
  • 프로그래머스
  • dp

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
dev_beomgeun

꾸준하게 차근차근

문제 풀이/백준 알고리즘

[baekjoon 20040] 사이클 게임 (유니온 파인드, union-find) (C++)

2021. 3. 21. 17:55
728x90

www.acmicpc.net/problem/20040

 

20040번: 사이클 게임

사이클 게임은 두 명의 플레이어가 차례대로 돌아가며 진행하는 게임으로, 선 플레이어가 홀수 번째 차례를, 후 플레이어가 짝수 번째 차례를 진행한다. 게임 시작 시 0 부터 n − 1 까지 고유한

www.acmicpc.net

유니온 파인드를 통해 사이클 판별을 하는 문제이다.

 

두 개의 정수가 주어지고, 그 둘은 연결되는데 선분들이 연결되다가 사이클이 발생할 때를 출력한다.

사이클이 생성되지 않을 경우 0을 출력.

 

#include <iostream>

using namespace std;

int parent[500001], n, m, from, to, answer;

int getParent(int x) {
	if (parent[x] == x)
		return x;
	else
		return parent[x] = getParent(parent[x]);
}

bool unionParent(int x, int y) {
	x = getParent(x);
	y = getParent(y);

	if (x == y)
		return true;
	else {
		if (x > y) {
			parent[x] = y;
		}
		else
			parent[y] = x;
	}
	return false;
}


int main() {
	cin >> n >> m;

	for (int i = 0; i < n; i++) {
		parent[i] = i;
	}
	for (int i = 0;  i < m; i++) {
		cin >> from >> to;
		if (unionParent(from, to) && answer == 0)
			answer = i + 1;
	}

	cout << answer;
}

유니온 함수를 약간 수정해서 합치기 전에 그 둘의 parent가 같다면 사이클이 생성된 경우이므로 true를 반환해주고, 아니면 합쳐주고 false를 반환하여 진행하였다.

 

ex)

6 5

parent 배열

0 1 2 3 4 5
0 1 2 3 4 5

0 1 (각각 0 하고 1이기 때문에 false 반환 후 parent 배열 update)

0 1 2 3 4 5
0 0 2 3 4 5

1 2 (각각 0 하고 2이기 때문에 false 반환 후 update)

0 1 2 3 4 5
0 0 0 3 4 5

1 3 (각각 0 하고 3이기에 false 반환)

0 1 2 3 4 5
0 0 0 0 4 5

0 3 (0과 0으로 cycle이 생성 -> true 반환)

4 5

 

union-find의 시간 복잡도

 

 유니온 파인드는 트리를 생성한다.

그리고 find함수는 재귀적으로 부모 노드가 루트 노드를 반환한다. 트리의 구조 상 최상위 노드는 루트로 자기 자신을 가리키고 있기 때문에 종료된다.

하지만 트리가 한쪽으로 치우친 경우, 매번 노드의 최상위 부모 노드를 찾기 위해서는 O(n)이 필요하다.

이 때문에 경로 압축을 사용한다. (트리의 높이를 줄여준다.)

즉, 루트 노드까지 도달 후 그 루트 노드 값을 가지고 내려오면서 자식 노드들의 부모를 루트 노드로 업데이트해준다.

 

따라서, find와 union 함수는 find의 시간 복잡도와 연결되어 있으며, 트리가 한쪽으로 치우쳤다면 O(n)이 소요된다.

하지만 경로 압축을 통해 O(a(n))이 되고, α(x)는 애커만 함수라고 하는데 x가 2의^65536일 때 함숫값이 5가 된다.

따라서, 그냥 O(1)이라고 생각해도 좋다고 한다.

 

 

728x90
저작자표시 비영리 변경금지 (새창열림)

'문제 풀이 > 백준 알고리즘' 카테고리의 다른 글

[baekjoon 1504] 특정한 최단 경로 (다익스트라) (C++)  (0) 2021.03.28
[baekjoon 2589] 보물섬 (BFS, 브루트포스) (C++)  (0) 2021.03.25
[baekjoon 2749] 피보나치 수 3 (DP, 피사노 주기) (C++)  (0) 2021.02.25
[baekjoon 1541] 잃어버린 괄호 (그리디, 문자열, 수학) (C++)  (0) 2021.02.22
[baekjoon 20548] 칠리소스 (수학, 브루트포스) (C++)  (0) 2021.02.21
    '문제 풀이/백준 알고리즘' 카테고리의 다른 글
    • [baekjoon 1504] 특정한 최단 경로 (다익스트라) (C++)
    • [baekjoon 2589] 보물섬 (BFS, 브루트포스) (C++)
    • [baekjoon 2749] 피보나치 수 3 (DP, 피사노 주기) (C++)
    • [baekjoon 1541] 잃어버린 괄호 (그리디, 문자열, 수학) (C++)
    dev_beomgeun
    dev_beomgeun
    백엔드 개발을 하며 얻은 지식과 경험을 공유합니다. 현재 카카오페이에서 백엔드 엔지니어로 일하고 있습니다.

    티스토리툴바