일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- 그리디
- 다이나믹 프로그래밍
- mysql
- 크루스칼 알고리즘
- greedy
- SERVLET
- 웹서버
- 벡엔드
- 프로그래머스
- 해시
- Kruskal's Algorithm
- 네이버 부스트캠프 ai tech
- 웹 프로그래밍
- mst
- 백준
- 웹프로그래밍
- 정렬
- BJ
- programmers
- 브라우저
- 정렬 알고리즘
- Prim's Algorithm
- 순열 알고리즘
- jsp
- request
- 프림 알고리즘
- 부스트코스
- 소수
- DP
- dbms
- Today
- Total
끵뀐꿩긘의 여러가지
BJ_ 2668 숫자 고르기, BJ_20040 사이클 게임 본문
문제 링크
https://www.acmicpc.net/problem/2668
2668번: 숫자고르기
세로 두 줄, 가로로 N개의 칸으로 이루어진 표가 있다. 첫째 줄의 각 칸에는 정수 1, 2, …, N이 차례대로 들어 있고 둘째 줄의 각 칸에는 1이상 N이하인 정수가 들어 있다. 첫째 줄에서 숫자를 적절
www.acmicpc.net
https://www.acmicpc.net/problem/20040
20040번: 사이클 게임
사이클 게임은 두 명의 플레이어가 차례대로 돌아가며 진행하는 게임으로, 선 플레이어가 홀수 번째 차례를, 후 플레이어가 짝수 번째 차례를 진행한다. 게임 시작 시 0 부터 n − 1 까지 고유한
www.acmicpc.net
문제 설명/ 풀이
- 그래프에서 사이클 찾기
사이클을 검출한다는 것은 그래프 내에 사이클이 존재하는지? 있다면 총 몇개가 존재하는지? 사이클에 포함된 노드는 무엇인지? 에 대해 알아내는 것이다.
- 무향 그래프에서의 사이클
무향 그래프에서의 사이클은 Union-Find를 통해 구할 수 있다.
union find에서 같은 부모를 가진 노드끼리 union을 하게 되면 사이클이 생긴다고 할 수 있다.
그러므로, 주어지는 입력값들을 계속해서 union 해주면서 같은 부모를 가진 노드끼리 union되는지만 살펴보면 된다.
코드:
import sys
sys.setrecursionlimit(10 ** 6)
m, n = map(int, sys.stdin.readline().split())
p = [i for i in range(m)]
def find(x):
if x == p[x]:
return x
p[x] = find(p[x])
return p[x]
def union(x, y):
x = find(x)
y = find(y)
if x == y:
return True # 사이클 생기면 true
# 아니면 작은 쪽으로 union
elif x > y:
p[x] = y
return False
else:
p[y] = x
return False
flag = 0
for i in range(n):
a, b = map(int, sys.stdin.readline().split())
if flag != 0: # 한번이라도 사이클이 생기면 입력만 받고 바로 넘김
continue
if union(a, b): # 사이클이 생기면 flag 변경
flag = i + 1
if flag == 0: # 사이클 x => 0출력
print(0)
else:
print(flag) # 사이클 O => 사이클 생긴 지점 출력
### 항상 작은 값 기준으로 혹은 항상 큰 값 기준으로 합치도록 하면,
### 트리의 높이가 낮아져서 시간이 빨라지는 효과가 있습니다.
- 유향 그래프에서의 사이클
유향 그래프에서는 DFS를 통해 사이클을 구할 수 있다.
DFS를 돌면서 자기 자신이 나온다면 사이클 안에 갇혀 있는 것이다.
코드:
# dfs
import sys
n = int(sys.stdin.readline())
# 인접한 노드에 대한 리스트를 만든다
arr = {i: [] for i in range(1, n + 1)}
for i in range(1,n+1):
m = int(sys.stdin.readline())
arr[m].append(i)
# 사이클에 존재하는 노드를 넣을 set
s = set()
for i in range(1,n+1):
q = []
if i in arr[i]: # 자기자신으로 그래프가 생기면 사이클 ex. 5->5
s.add(i)
continue
q.extend(arr[i]) # 인접 노드 리스트 넣어주기
while q:
new = q.pop()
if i in arr[new]: # DFS를 돌다가 자기 자신이 나오면
s.add(i) # 그 노드는 cycle의 구성요소이다.
break
q.extend(arr[new])
print(len(s)) # 노드개수
for i in sorted(s): # 노드
print(i)
다른 사람의 풀이
import sys
input = sys.stdin.readline
n = int(input())
num = [0] # 1부터 시작하기 위한 배열
for i in range(n):
num.append(int(input()))
def dfs(v, i):
visited[v] = True # 방문처리
next = num[v] # 다음으로 방문할 노드
if not visited[next]: # 방문하지 않은 곳 방문
dfs(next, i)
elif visited[next] and next == i: # 방문했고, 자기자신인 노드가 나오면 cycle의 구성요소
result.append(next)
result = list() # 사이클에 존재하는 노드를 넣을 배열
for i in range(1,n+1):
visited = [False]*(n+1) # 처음에는 방문 x
dfs(i, i) # i(자기자신)부터 방문
print(len(result))
for r in result:
print(r)
그래프 방향을 반대로 생각하여 방문 처리를 하여 풀었다.
'Naver boostcamp -ai tech > 알고리즘 풀이' 카테고리의 다른 글
벡준 2138번, 전구와 스위치 (0) | 2022.11.15 |
---|---|
BJ_ 14719 그림 (0) | 2022.10.10 |
BJ_ 2054 괄호의 값 (0) | 2022.10.03 |
BJ_ 14719 빗물 (0) | 2022.09.27 |
BJ_ 14888 연산자 끼워넣기 (0) | 2022.09.27 |