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를 충분히 안 받을 수 있습니다. 😆