From 8a38c930c4f1671f012f3d69c116ec7ff9465983 Mon Sep 17 00:00:00 2001 From: Gyunseo Lee <rbstj0311@naver.com> Date: Thu, 4 Jul 2024 23:06:16 +0900 Subject: [PATCH] 2024-07-04 23:06:16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Affected files: .obsidian/workspace.json src/content/blog/boj-10159-저울.md --- .obsidian/workspace.json | 24 ++-- .../boj-10159-\354\240\200\354\232\270.md" | 104 ++++++++++++++++++ 2 files changed, 116 insertions(+), 12 deletions(-) create mode 100644 "src/content/blog/boj-10159-\354\240\200\354\232\270.md" diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index 5556f7421..010816b2a 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -13,7 +13,7 @@ "state": { "type": "markdown", "state": { - "file": "src/content/blog/leet-code-letter-combinations-of-a-phone-number.md", + "file": "src/content/blog/boj-1926-그림.md", "mode": "source", "source": false } @@ -22,16 +22,16 @@ ] }, { - "id": "5dcc65a347118080", + "id": "2fc2c57290be6233", "type": "tabs", "children": [ { - "id": "88cef06b4dd7f423", + "id": "4de88d0967b6111b", "type": "leaf", "state": { "type": "markdown", "state": { - "file": "src/content/blog/leet-code-longest-continuous-subarray-with-absolute-diff-less -than-or-equal-to-Limit.md", + "file": "src/content/blog/boj-10159-저울.md", "mode": "source", "source": false } @@ -103,7 +103,7 @@ "state": { "type": "backlink", "state": { - "file": "src/content/blog/leet-code-longest-continuous-subarray-with-absolute-diff-less -than-or-equal-to-Limit.md", + "file": "src/content/blog/boj-10159-저울.md", "collapseAll": false, "extraContext": false, "sortOrder": "alphabetical", @@ -120,7 +120,7 @@ "state": { "type": "outgoing-link", "state": { - "file": "src/content/blog/leet-code-longest-continuous-subarray-with-absolute-diff-less -than-or-equal-to-Limit.md", + "file": "src/content/blog/boj-10159-저울.md", "linksCollapsed": false, "unlinkedCollapsed": true } @@ -143,7 +143,7 @@ "state": { "type": "outline", "state": { - "file": "src/content/blog/leet-code-longest-continuous-subarray-with-absolute-diff-less -than-or-equal-to-Limit.md" + "file": "src/content/blog/boj-10159-저울.md" } } } @@ -166,13 +166,14 @@ "table-editor-obsidian:Advanced Tables Toolbar": false } }, - "active": "88cef06b4dd7f423", + "active": "4de88d0967b6111b", "lastOpenFiles": [ - "src/content/blog/leet-code-longest-continuous-subarray-with-absolute-diff-less -than-or-equal-to-Limit.md", + "src/content/blog/boj-10159-저울.md", + "src/content/blog/boj-1926-그림.md", "src/content/blog/leet-code-letter-combinations-of-a-phone-number.md", + "src/content/blog/leet-code-longest-continuous-subarray-with-absolute-diff-less -than-or-equal-to-Limit.md", "src/content/blog/boj-11057-오르막-수.md", "dist/posts/boj-백준-11507-오르막-수.png", - "src/content/blog/boj-1926-그림.md", "src/content/blog/boj-11057-.md", "src/content/blog/leet-code-minimum-path-sum.md", "src/content/blog/boj-1940-주몽.md", @@ -212,7 +213,6 @@ "src/content/blog/boj-10819-차이를-최대로.md", "src/content/blog/boj-2230-수-고르기.md", "src/content/blog/boj-1912-연속합.md", - "src/content/blog/boj-1699-제곱수의-합.md", - "src/content/blog/boj-1026-보물.md" + "src/content/blog/boj-1699-제곱수의-합.md" ] } \ No newline at end of file diff --git "a/src/content/blog/boj-10159-\354\240\200\354\232\270.md" "b/src/content/blog/boj-10159-\354\240\200\354\232\270.md" new file mode 100644 index 000000000..fb087c624 --- /dev/null +++ "b/src/content/blog/boj-10159-\354\240\200\354\232\270.md" @@ -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를 충분히 안 받을 수 있습니다. 😆