forked from satnaing/astro-paper
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Affected files: .obsidian/workspace.json src/content/blog/boj-10159-저울.md
- Loading branch information
Showing
2 changed files
with
116 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
--- | ||
author: Gyunseo Lee | ||
title: "BOJ 백준 10159: 저울" | ||
pubDatetime: 2024-07-04T22:44:00+09:00 | ||
modDatetime: 2024-07-04T22:44:00+09:00 | ||
featured: false | ||
draft: false | ||
tags: | ||
- PS | ||
description: this is template | ||
ogImage: "" | ||
--- | ||
|
||
## Table of contents | ||
|
||
## 들어가며 | ||
|
||
걸린시간: 30분 | ||
|
||
처음에 문제를 읽으면서, 물건 쌍의 비교 결과들만으로 각 물건에 대해 딴 물건들과의 비교 결과를 유추하고, 유추 결과를 알 수 없는 물건들의 개수를 보자 마자, 위상 정렬을 떠올렸습니다. | ||
왜냐면요 옛날에, https://www.acmicpc.net/problem/2252 이 문제를 위상정렬로 풀었던 기억이 났었습니다. | ||
N최대 100이고, M의 최대는 2000이어서 O(N + M)으로 그래프를 충분히 순회할 수 있겠다 생각하고 접근했습니다. | ||
|
||
## 접근 | ||
|
||
![](https://res.cloudinary.com/gyunseo-blog/image/upload/f_auto/v1720101587/image_vcielz.png) | ||
|
||
처음에는 입력 받은 두 수의 순서대로 유향 그래프를 그렸습니다. | ||
그리고 각 숫자에서 DFS를 이용해서, 그래프 순회를 해서 방문하지 못한 노드의 개수를 세면 된다고 생각했습니다. | ||
예를 들어 위 노트에 적힌 것을 예시로 들자면요. | ||
2에서 DFS 순회를 시작하면, 2, 3, 4를 방문하고, 1, 5, 6은 방문하지 못하게 됩니다. | ||
어? 그러면 저희 문제 조건과 위배가 되게 되죠? 5, 6은 2와 비교 결과를 결정짓지 못하는 게 맞는데, 1은 2보다 확실히 큰 경우이잖아요. | ||
그래서 생각난 게, 역방향 그래프를 주어서, 거기서 또 다시 한번 DFS순회를 하는 겁니다. | ||
그렇게 되면 2, 1을 방문하게 되고, 3, 4, 5, 6은 방문하지 못하게 됩니다. | ||
그러면 정방향과 역방향 그래프 모두에서 방문되지 못한 노드가 결국 비교 결과를 결정짓지 못하는 숫자이지요? | ||
제가 그렇게 발상을 했었던 이유는요. | ||
몇 달 전에 소프티어 문제를 풀면서 비슷한 문제를 풀어 봤어서 그랬습니다. | ||
https://softeer.ai/practice/6248 출퇴근길이라는 문제인데 한번 풀어 보세요. | ||
|
||
## 구현 | ||
|
||
```python | ||
import sys | ||
|
||
input = sys.stdin.readline | ||
|
||
|
||
def DFS(cur_node): | ||
|
||
for next_node in graph[cur_node]: | ||
if isVisited[next_node]: | ||
continue | ||
|
||
isVisited[next_node] = True | ||
DFS(next_node) | ||
|
||
|
||
def reversedDFS(cur_node): | ||
for next_node in reversedGraph[cur_node]: | ||
if reversedIsVisited[next_node]: | ||
continue | ||
|
||
reversedIsVisited[next_node] = True | ||
reversedDFS(next_node) | ||
|
||
|
||
def resetVisitedLists(): | ||
for i in range(N + 1): | ||
isVisited[i] = False | ||
reversedIsVisited[i] = False | ||
|
||
|
||
if __name__ == "__main__": | ||
N = int(input().strip()) | ||
M = int(input().strip()) | ||
# graph[u].append(v) -> u가 v보다 크다 | ||
graph = [[] for _ in range(N + 1)] | ||
isVisited = [False for _ in range(N + 1)] | ||
ans = [0 for _ in range(N + 1)] | ||
# graph[v].append(u) -> v가 u보다 작다를 저장하는 리스트 | ||
reversedGraph = [[] for _ in range(N + 1)] | ||
reversedIsVisited = [False for _ in range(N + 1)] | ||
for _ in range(M): | ||
u, v = map(int, input().strip().split()) | ||
graph[u].append(v) | ||
reversedGraph[v].append(u) | ||
|
||
# O(N * (N + M + 2N)) | ||
for i in range(1, N + 1): | ||
isVisited[i] = True | ||
DFS(i) | ||
reversedIsVisited[i] = True | ||
reversedDFS(i) | ||
for j in range(1, N + 1): | ||
if not isVisited[j] and not reversedIsVisited[j]: | ||
ans[i] += 1 | ||
resetVisitedLists() | ||
|
||
for i in range(1, N + 1): | ||
print(ans[i]) | ||
|
||
``` | ||
|
||
인접 리스트를 이용해서 DFS를 구현하면, 시간 복잡도는 O(N+M)입니다. 근데 이 DFS를 각 노드마다 해주니 시간 복잡도는 O(N(N+M))이고, 이는 TLE를 충분히 안 받을 수 있습니다. 😆 |