<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>All around the world</title>
    <link>https://5as2s.tistory.com/</link>
    <description>개구리는 파충류가 아니다.</description>
    <language>ko</language>
    <pubDate>Sat, 30 May 2026 09:07:10 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>miwat</managingEditor>
    <image>
      <title>All around the world</title>
      <url>https://tistory1.daumcdn.net/tistory/4200203/attach/2a713550ebe9473596b915e6b30a775c</url>
      <link>https://5as2s.tistory.com</link>
    </image>
    <item>
      <title>[백준/Python]23286: 허들 넘기</title>
      <link>https://5as2s.tistory.com/394</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/23286&quot;&gt;https://www.acmicpc.net/problem/23286&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준 문제집 - 0x1C강 - 플로이드 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;알고리즘: &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;그래프 이론&lt;/span&gt;, 최단 경로, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;데이크스트라&lt;/span&gt;, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;플로이드-워셜&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;622&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cx5HqS/btsQYbJYtPm/8Y0FxK128DD9CIH528tizk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cx5HqS/btsQYbJYtPm/8Y0FxK128DD9CIH528tizk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cx5HqS/btsQYbJYtPm/8Y0FxK128DD9CIH528tizk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcx5HqS%2FbtsQYbJYtPm%2F8Y0FxK128DD9CIH528tizk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1460&quot; height=&quot;622&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;622&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출발노드를 &lt;b&gt;A&lt;/b&gt;, 도착노드를 &lt;b&gt;B&lt;/b&gt;라 했을때 &lt;b&gt;A에서 B로 가는 경로&lt;/b&gt;는 여러가지가 될 것이다.&lt;br /&gt;각 경로(A-K-B)에서 &lt;b&gt;가장 높은 허들을 h라 했을때,&lt;/b&gt; &lt;code&gt;h1, h2, h3...&lt;/code&gt; 중 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;&lt;b&gt;가장 작은 값&lt;/b&gt;&lt;/span&gt;이 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;&lt;b&gt;A-B 경로의 값&lt;/b&gt;&lt;/span&gt;이 되는것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 &lt;code&gt;graph[A][K]&lt;/code&gt;의 높이가 3, &lt;code&gt;graph[K][B]&lt;/code&gt;의 높이가 6이라면 A-K-B의 경로는 6이 된다.&lt;br /&gt;이런식으로 &lt;u&gt;&lt;b&gt;모든 정점 K를 중간 노드로 두고 각 경로마다 가장 높은 허들을 체크&lt;/b&gt;&lt;/u&gt;한다.&lt;br /&gt;(기존 &lt;code&gt;graph[A][B]&lt;/code&gt;값이 4라면 &lt;code&gt;4 &amp;lt; 6&lt;/code&gt;이니 갱신하지 않고 그대로 두는 식.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 이 문제... 예전에 &lt;b&gt;플로이드워셜&lt;/b&gt; + Python3로 제출했을때는 &lt;span style=&quot;color: #ee2323;&quot;&gt;시간초과&lt;/span&gt; 판정을 받았다.&lt;br /&gt;풀이글을 작성하며 좀 더 다듬어서 다시 제출해보니 통과된다. 기준이 완화된듯?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;b&gt;다익스트라&lt;/b&gt;를 사용하는 풀이보다는 느리다. 사실 이 문제는 다익스트라를 사용하면 빠른 시간으로 통과할 수 있다!&lt;br /&gt;(플로이드 워셜 사용시: 2056ms / 다익스트라 사용시: 600ms)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;405&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFDgpX/btsQXPApTKt/aNs1QDvmBFednpJWQIpRFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFDgpX/btsQXPApTKt/aNs1QDvmBFednpJWQIpRFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFDgpX/btsQXPApTKt/aNs1QDvmBFednpJWQIpRFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFDgpX%2FbtsQXPApTKt%2FaNs1QDvmBFednpJWQIpRFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;259&quot; height=&quot;251&quot; data-origin-width=&quot;405&quot; data-origin-height=&quot;392&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 자체는 플로이드 워셜 유형이지만, &lt;u&gt;노드는 최대 300개&lt;/u&gt;가 주어질 수 있는 반면에 &lt;u&gt;간선은 최대 25,000개&lt;/u&gt;만 주어진다.&lt;br /&gt;모든 노드가 이어져있다고 가정했을때의 간선 수는 90,000개 이므로 &lt;u&gt;실제보다 훨씬 적은 값&lt;/u&gt;이 주어지는 셈이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 다익스트라 사용 풀이 (&lt;code&gt;heapq&lt;/code&gt;)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;&lt;b&gt;간선 정보 저장&lt;/b&gt;&lt;/span&gt; / &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;&lt;b&gt;계산값 갱신&lt;/b&gt;&lt;/span&gt;을 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;&lt;b&gt;분리&lt;/b&gt;&lt;/span&gt;해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 간선 정보 저장은 2차원 딕셔너리(&lt;code&gt;{a: {b: h}}&lt;/code&gt;)를, 갱신은 2차원 리스트를 사용했다. 둘 다 리스트로 관리해도 상관은 없지만 위에서 말했다시피 간선 갯수는 노드 수에 비해 적으므로 &lt;b&gt;딕셔너리를 활용하는게 더 효율적&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 모든 노드를 시작점으로 두며 다익스트라를 실행한다. 초기 힙(&lt;b&gt;최소힙)&lt;/b&gt;에는 &lt;code&gt;(0, 시작노드)&lt;/code&gt;가 들어있다.&lt;br /&gt;힙이 빌 때까지 아래 과정을 반복한다.&lt;br /&gt;(&lt;code&gt;graph&lt;/code&gt; = 초기 간선 값 / &lt;code&gt;heights&lt;/code&gt; = A-B 허들 높이 계산값)&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;code&gt;(높이, 노드)&lt;/code&gt;를 힙에서 꺼낸다.&lt;/li&gt;
&lt;li&gt;만약 꺼낸 높이값이 &lt;code&gt;heights[시작점][노드]&lt;/code&gt;보다 크다면, 이미 확인한 노드이므로 넘어간다.&lt;/li&gt;
&lt;li&gt;아니라면 노드와 연결된 간선 정보들을 확인한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 노드에서 갈 수 있는 노드를 &lt;code&gt;nxt&lt;/code&gt;라고 했을때, &lt;code&gt;graph[노드][nxt]&lt;/code&gt;값과 현재 높이 값을 비교한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;둘 중 더 큰값&lt;/b&gt;을 &lt;b&gt;최대 허들 높이&lt;/b&gt;로 선정. (최대 허들 높이)&lt;/li&gt;
&lt;li&gt;만약 이 값이 기존의 &lt;code&gt;heights[시작노드][nxt]&lt;/code&gt;값보다 작다면 갱신, 힙에 추가. (최소값)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;&lt;b&gt;힙에 들어있는 높이값&lt;/b&gt;&lt;/span&gt;은 &lt;b&gt;시작점에서 현재 노드까지 가는 경로들 중&lt;/b&gt;에서 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;&lt;b&gt;&quot;가장 높은 허들&quot;&lt;/b&gt;&lt;/span&gt;을 의미한다.&lt;br /&gt;하지만 최소 힙에 저장했으니 &lt;code&gt;pop&lt;/code&gt;되는 값은 &lt;b&gt;여러개의 시작노드 &amp;rarr; 현재노드 경로 중&lt;/b&gt; &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;&lt;b&gt;가장 최소의 최대 허들 높이&lt;/b&gt;&lt;/span&gt;값이 되는것이다.&lt;br /&gt;같은 노드에 도달하더라도 어떤 경로로 왔느냐에 따라 최대 허들 높이가 달라지는거다.&lt;br /&gt;&lt;code&gt;pop&lt;/code&gt;한 높이값과 &lt;code&gt;nxt&lt;/code&gt; 사이의 허들 높이값을 비교해서 &lt;b&gt;더 높은 허들을 &lt;code&gt;new_h&lt;/code&gt;로 결정&lt;/b&gt;하고, 이 값이 &lt;b&gt;기존의 시작노드 &amp;rarr; &lt;code&gt;nxt&lt;/code&gt; 경로의 높이값보다 작으면 갱신&lt;/b&gt;하는것!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;전체 코드&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 메모리: 37452KB / 시간: 600ms
from sys import stdin
from collections import defaultdict
from heapq import heappop, heappush


input = stdin.readline
INF = int(1e9)

N, M, T = map(int, input().split())
# 2차원 딕셔너리 생성
# graph[a][b] = {a: {b: 허들 높이}}
graph = defaultdict(dict)

for _ in range(M):
    u, v, h = map(int, input().split())
    graph[u][v] = h


def dijkstra(start):
    queue = []
    heappush(queue, (0, start))

    while queue:
        curr_h, curr = heappop(queue)

        if heights[start][curr] &amp;lt; curr_h:
            continue

        for nxt, h in graph[curr].items():
            new_h = max(h, curr_h)
            if new_h &amp;lt; heights[start][nxt]:
                heights[start][nxt] = new_h
                heappush(queue, (new_h, nxt))


heights = [[INF] * (N+1) for _ in range(N+1)]

# 다익스트라로 모든 노드를 시작점으로 두고 최단경로 구하기
for i in range(1, N+1):
    heights[i][i] = 0
    dijkstra(i)

for _ in range(T):
    s, e = map(int, input().split())
    ret = heights[s][e]
    print(ret if ret != INF else -1)&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 플로이드-워셜 사용 풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플로이드를 사용하면 비교적 간단해진다.&lt;br /&gt;k-i-j로 플로이드 워셜을 수행하면서 필요한 조건만 체크해주면 된다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;code&gt;graph[i][k]&lt;/code&gt;와 &lt;code&gt;graph[k][j]&lt;/code&gt;의 값이 &lt;code&gt;INF&lt;/code&gt;인지 확인한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;INF&lt;/code&gt;라면 불가능한 경로이므로 넘어감.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;graph[i][k]&lt;/code&gt;의 허들 높이, &lt;code&gt;graph[k][j]&lt;/code&gt;의 허들 높이 중 더 큰 값을 선택. (최대 허들 높이)&lt;/li&gt;
&lt;li&gt;만약 이 값이 기존의 &lt;code&gt;graph[i][j]&lt;/code&gt;값보다 작다면 갱신한다. (최소값)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;전체 코드&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 메모리: 33432KB / 시간: 2056ms
from sys import stdin


input = stdin.readline
INF = int(1e9)

def main():
    N, M, T = map(int, input().split())
    graph = [[INF if i != j else 0 for j in range(N)] for i in range(N)]

    for _ in range(M):
        u, v, h = map(int, input().split())
        graph[u-1][v-1] = h

    for k in range(N):
        for i in range(N):
            for j in range(N):
                if graph[i][k] == INF or graph[k][j] == INF:
                    continue

                # i-k 경로의 허들과 k-j 경로의 허들 중 더 높은값
                max_h = max(graph[i][k], graph[k][j])
                if graph[i][j] &amp;gt; max_h:
                    graph[i][j] = max_h

    for _ in range(T):
        s, e = map(int, input().split())
        print(graph[s-1][e-1] if graph[s-1][e-1] != INF else -1)


main()&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 직관적으로 이해하기 쉬운건 플로이드 워셜이다. (흑흑)&lt;/p&gt;</description>
      <category>  Algorithm/  Baekjoon</category>
      <category>23286 파이썬</category>
      <category>python</category>
      <category>그래프 이론</category>
      <category>다익스트라</category>
      <category>데이크스트라</category>
      <category>백준</category>
      <category>백준 23286</category>
      <category>백준 파이썬</category>
      <category>플로이드워셜</category>
      <author>miwat</author>
      <guid isPermaLink="true">https://5as2s.tistory.com/394</guid>
      <comments>https://5as2s.tistory.com/394#entry394comment</comments>
      <pubDate>Wed, 1 Oct 2025 16:57:36 +0900</pubDate>
    </item>
    <item>
      <title>[백준/Python]13314: 플로이드에 오타가?</title>
      <link>https://5as2s.tistory.com/393</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/13314&quot;&gt;https://www.acmicpc.net/problem/13314&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준 문제집 - 0x1C강 - 플로이드 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;알고리즘: 그래프 이론, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;해 구성하기&lt;/span&gt;, 최단 경로, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;플로이드-워셜&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1453&quot; data-origin-height=&quot;737&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lYyOI/btsQVJ0pweY/DqzKkkkRIoEPsSyu2RkgK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lYyOI/btsQVJ0pweY/DqzKkkkRIoEPsSyu2RkgK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lYyOI/btsQVJ0pweY/DqzKkkkRIoEPsSyu2RkgK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlYyOI%2FbtsQVJ0pweY%2FDqzKkkkRIoEPsSyu2RkgK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1453&quot; height=&quot;737&quot; data-origin-width=&quot;1453&quot; data-origin-height=&quot;737&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 접하는 유형이라 굉장히 당황스러웠던 문제... 다른 풀이 + GPT를 참고해서 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;결론부터 말하자면 9700개 이상의 차이가 발생하는 &quot;데이터&quot;를 찾아야 하는 문제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 지구이씨의 코드는 파일로 첨부되어 있는데, 살펴보면 아래와 같다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;# 조건
if( i == j &amp;amp;&amp;amp; D[i][j] != 0 || D[i][j] &amp;gt; 10000) WRONG;

# 첫번째 코드
for(int k = 1; k &amp;lt; N; k++){
    for(int i = 1; i &amp;lt;= N; i++){
        for(int j = 1; j &amp;lt;= N; j++){
            D[i][j] = min(D[i][k] + D[k][j], D[i][j]);
        }
    }
}

# 두번째 코드는 맞음&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;중간 거점 노드 k의 범위를 1 ~ N으로 설정해야 하는데, N-1까지만 확인한다.&lt;/u&gt;&lt;br /&gt;즉 &lt;code&gt;D[i][N] + D[N][j]&lt;/code&gt;의 경우를 아예 체크하지 않은것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이 데이터를 기준으로 T/F가 나뉘려면 어떻게 해야할까?&lt;br /&gt;  &lt;code&gt;D[i][j]&lt;/code&gt;값이 실제로는 &lt;code&gt;D[i][N] + D[N][i]&lt;/code&gt;여야 맞는 풀이라는것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 &lt;b&gt;데이터가 틀리려면 &lt;code&gt;D[i][N] + D[N][i]&lt;/code&gt;가 &lt;code&gt;D[i][j]&lt;/code&gt;보다 작아야 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;반대로 맞는 데이터들은 두 가지 경우가 있겠다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;code&gt;D[i][i]&lt;/code&gt;: &lt;b&gt;주대각선&lt;/b&gt;(0이어야 함)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;D[i][N]&lt;/code&gt;, &lt;code&gt;D[N][i]&lt;/code&gt;: 거쳐가지 않고 직접 연결
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;직접 연결된 간선&lt;/b&gt;이므로 플로이드 워셜이 어떻게 돌아가든 항상 같음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 조건에 부합하는 데이터의 갯수를 &lt;code&gt;cnt&lt;/code&gt;라고 가정해보자.&lt;br /&gt;틀린 데이터의 갯수가 9700개 이상이어야 한다고 했으니 &lt;code&gt;N*N - cnt&lt;/code&gt; &amp;gt;= 9700 을 만족하면 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계산 돌려보면 &lt;code&gt;N = 100&lt;/code&gt;일때 1번 조건의 갯수는 100, 2번 조건의 갯수는 99 * 2 = 198(&lt;code&gt;D[i][99]&lt;/code&gt;, &lt;code&gt;D[99][j]&lt;/code&gt;와 같이 출발/도착노드가 99가 아닌경우)가 나온다.&lt;br /&gt;100 * 100 = 10000, 100 + 189 = 298이니까 10000 - 298 = 9702개가 되므로 문제의 조건을 만족한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고로 틀린 데이터가 9700개 이상이 나오는 코드는,&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;100 * 100 행렬&lt;/li&gt;
&lt;li&gt;&lt;code&gt;D[i][99]&lt;/code&gt; = &lt;code&gt;D[99][j]&lt;/code&gt; = 1&lt;/li&gt;
&lt;li&gt;&lt;code&gt;i=i&lt;/code&gt;인 주대각선의 값은 0&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 되어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이렇게 하면&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;첫번째 코드: &lt;code&gt;D[i][j]&lt;/code&gt; = 100&lt;/li&gt;
&lt;li&gt;두번째 코드: &lt;code&gt;D[i][j]&lt;/code&gt; = &lt;code&gt;D[i][99]&lt;/code&gt; + &lt;code&gt;D[99][j]&lt;/code&gt; = 2&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가 되므로 차이가 생기게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 코드&lt;/h3&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 9700개 이상의 차이가 발생하는 &quot;데이터&quot;를 찾아야 하는 문제다.
&quot;&quot;&quot;
100x100 행렬로 만들 수 있는 쌍의 갯수 = 100 * 100 = 10,000개
제대로 계산한 값과 틀린 계산의 값이 같은 경우를 cnt라고 했을때,
- (i, i): 주대각선 행렬 100개
- (i, k), (k, j): 출발지 or 도착지가 k인경우 99 * 2 = 198개
10,000개 - 298개 = 9702개가 되므로 N = 100이고 (i, k), (k, j)가 (i, j)보다 작을 때 &quot;데이터&quot;를 만족함.
&quot;&quot;&quot;
# 메모리: 32412KB / 시간: 36ms
N = 100

arr = [[100] * N for _ in range(N)]

for i in range(100):
    arr[i][99] = arr[99][i] = 1
    arr[i][i] = 0

print(N)

for line in arr:
    print(*line)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플로이드 워셜을 이해했는가를 검증하는 느낌이다.&lt;/p&gt;</description>
      <category>  Algorithm/  Baekjoon</category>
      <category>13314 파이썬</category>
      <category>python</category>
      <category>백준</category>
      <category>백준 13314</category>
      <category>백준 파이썬</category>
      <category>플로이드워셜</category>
      <category>해 구성하기</category>
      <author>miwat</author>
      <guid isPermaLink="true">https://5as2s.tistory.com/393</guid>
      <comments>https://5as2s.tistory.com/393#entry393comment</comments>
      <pubDate>Mon, 29 Sep 2025 21:19:49 +0900</pubDate>
    </item>
    <item>
      <title>[백준/Python]1719: 택배</title>
      <link>https://5as2s.tistory.com/390</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1719&quot;&gt;https://www.acmicpc.net/problem/1719&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준 문제집 - 0x1C강 - 플로이드 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;알고리즘: 그래프 이론, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;최단 경로&lt;/span&gt;, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;데이크스트라&lt;/span&gt;, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;플로이드-워셜&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1474&quot; data-origin-height=&quot;1161&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0Qh3x/btsQQchoy5a/vnL6lpa1XpiZgvjmeEwos0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0Qh3x/btsQQchoy5a/vnL6lpa1XpiZgvjmeEwos0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0Qh3x/btsQQchoy5a/vnL6lpa1XpiZgvjmeEwos0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0Qh3x%2FbtsQQchoy5a%2FvnL6lpa1XpiZgvjmeEwos0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1474&quot; height=&quot;1161&quot; data-origin-width=&quot;1474&quot; data-origin-height=&quot;1161&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;최단경로&lt;/b&gt;를 구해야 하니 &lt;b&gt;플로이드 워셜은 필수&lt;/b&gt;고, 추가로 경로표(&lt;b&gt;다음에 방문할 노드&lt;/b&gt;)도 구해야 한다.&lt;br /&gt;(&lt;a href=&quot;https://5as2s.tistory.com/358&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;11780: 플로이드 2&lt;/a&gt;를 풀어봤다면 쉬운 문제다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;최단경로용 리스트&lt;/span&gt; / &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;경로 저장용 리스트&lt;/span&gt;를 &lt;b&gt;따로 생성&lt;/b&gt;해야 한다.&lt;br /&gt;각 리스트는 다음과 같이 구성 될 예정이다.&lt;br /&gt;&lt;code&gt;graph[a][b]&lt;/code&gt;: a에서 b로 가는 최단거리&lt;br /&gt;&lt;code&gt;nxt[a][b]&lt;/code&gt;: a에서 b로 갈 때, a 다음으로 방문할 노드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(a, b)가 같은 &lt;u&gt;중복 데이터는 주어지지 않으니&lt;/u&gt; 입력 데이터 그대로 리스트에 저장해주면 된다.&lt;/p&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;graph[a][b] = c
nxt[a][b] = b&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;b&gt;플로이드 워셜을 수행&lt;/b&gt;하면서 &lt;b&gt;경로표를 갱신&lt;/b&gt;해준다.&lt;br /&gt;만약 &lt;b&gt;a-b 루트&lt;/b&gt;보다 &lt;b&gt;a-k + k-b 루트&lt;/b&gt;가 &lt;b&gt;더 효율적&lt;/b&gt;이라면 a 다음에 &lt;code&gt;nxt[a][k]&lt;/code&gt; 노드로 가야 한다.&lt;/p&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;if graph[a][b] &amp;gt; graph[a][k] + graph[k][b]:
    graph[a][b] = graph[a][k] + graph[k][b]
    nxt[a][b] = nxt[a][k]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 갱신하다보면 &lt;b&gt;&lt;code&gt;nxt[a][b]&lt;/code&gt;&lt;/b&gt;에는 &lt;b&gt;&quot;a 방문 후, 바로 다음으로 방문해야 할 노드&quot;&lt;/b&gt;가 저장될것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt; 이해가 잘 안될경우 아래의 질문글을 참고해보면 좋을것같다.&lt;br /&gt;&lt;a href=&quot;https://www.acmicpc.net/board/view/104174&quot;&gt;https://www.acmicpc.net/board/view/104174&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 코드&lt;/h3&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 메모리: 33432KB / 시간: 584ms
from sys import stdin


input = stdin.readline
INF = int(1e9)

def main():
    N, M = map(int, input().split())
    graph = [[INF] * N for _ in range(N)]
    nxt = [[-1] * N for _ in range(N)]

    for _ in range(M):
        u, v, w = map(int, input().split())
        graph[u-1][v-1] = w
        graph[v-1][u-1] = w

        nxt[u-1][v-1] = v
        nxt[v-1][u-1] = u

    for k in range(N):
        for i in range(N):
            for j in range(N):
                if graph[i][j] &amp;gt; graph[i][k] + graph[k][j]:
                    graph[i][j] = graph[i][k] + graph[k][j]
                    nxt[i][j] = nxt[i][k]

    for i in range(N):
        line = [&quot;-&quot; if i == j else nxt[i][j] for j in range(N)]
        print(*line)


main()&lt;/code&gt;&lt;/pre&gt;</description>
      <category>  Algorithm/  Baekjoon</category>
      <category>1719 파이썬</category>
      <category>python</category>
      <category>데이크스트라</category>
      <category>백준</category>
      <category>백준 1719</category>
      <category>백준 파이썬</category>
      <category>최단경로</category>
      <category>플로이드워셜</category>
      <author>miwat</author>
      <guid isPermaLink="true">https://5as2s.tistory.com/390</guid>
      <comments>https://5as2s.tistory.com/390#entry390comment</comments>
      <pubDate>Thu, 25 Sep 2025 22:09:05 +0900</pubDate>
    </item>
    <item>
      <title>[백준/Python]1507: 궁금한 민호</title>
      <link>https://5as2s.tistory.com/388</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1507&quot;&gt;https://www.acmicpc.net/problem/1507&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준 문제집 - 0x1C강 - 플로이드 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;알고리즘: &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;그래프 이론&lt;/span&gt;, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;최단 경로&lt;/span&gt;, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;플로이드-워셜&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1455&quot; data-origin-height=&quot;766&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckcHkS/btsQLarXWfg/LlL9mcgBNUG7HKj2XJFIrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckcHkS/btsQLarXWfg/LlL9mcgBNUG7HKj2XJFIrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckcHkS/btsQLarXWfg/LlL9mcgBNUG7HKj2XJFIrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckcHkS%2FbtsQLarXWfg%2FLlL9mcgBNUG7HKj2XJFIrk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1455&quot; height=&quot;766&quot; data-origin-width=&quot;1455&quot; data-origin-height=&quot;766&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;모든 A-B(B-A)는 연결되어있다.(직접 or 우회)&lt;/li&gt;
&lt;li&gt;주어진 간선들은 모두 최단경로 값이다.&lt;/li&gt;
&lt;li&gt;단, 갯수는 &quot;최소&quot;가 아니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 주어진 값들로 A-B 쌍의 거리를 구했을때 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;최단경로를 만족하는지 확인&lt;/span&gt;해야한다. 최소 갯수를 만족하는지는 다음 문제다.&lt;br /&gt;&lt;b&gt;A-B 직행&lt;/b&gt;보다 &lt;b&gt;A-K + K-B 우회값이 더 크다면&lt;/b&gt; 최단경로가 아닌 셈. (같은 경우는 괜찮다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;첫번째 조건을 만족하지 못했다면 바로 &lt;code&gt;-1&lt;/code&gt;를 출력해주고, 만족했다면 다음 단계로 넘어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제와 함께 보면 이해가 쉽다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1447&quot; data-origin-height=&quot;117&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/prjyM/btsQLfmt666/83S0bb8KkQQoJhM0vc3nrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/prjyM/btsQLfmt666/83S0bb8KkQQoJhM0vc3nrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/prjyM/btsQLfmt666/83S0bb8KkQQoJhM0vc3nrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FprjyM%2FbtsQLfmt666%2F83S0bb8KkQQoJhM0vc3nrK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1447&quot; height=&quot;117&quot; data-origin-width=&quot;1447&quot; data-origin-height=&quot;117&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;꼭 &lt;b&gt;필요한 도로만&lt;/b&gt; 남겨두고 &lt;b&gt;나머지는 제거&lt;/b&gt;한다. &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;남겨둔 도로들의 합&lt;/span&gt;이 문제에서 말하는 &quot;모든 도로의 시간의 합&quot;이 되는것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 &lt;b&gt;A-B(직행값) == A-K + K-B(우회값)&lt;/b&gt;이라면 &lt;b&gt;A-B 도로는 굳이 필요하지 않다.&lt;/b&gt; 같은 비용으로 우회해서 갈 수 있기 때문.&lt;br /&gt;따라서 &lt;b&gt;직행값&lt;/b&gt;이 &lt;b&gt;우회값&lt;/b&gt;보다 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;적을 경우에만 결과값에 추가&lt;/span&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체적인 과정은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;플로이드 워셜을 수행하며 &lt;b&gt;최단경로를 만족하는지 확인.&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;u&gt;&lt;b&gt;갱신은 X&lt;/b&gt;&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;A-K + K-B 값이 더 효율적이라면? 주어진 값들이 최단경로가 아닌것이므로 -1를 반환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다시 한 번 플로이드 워셜을 수행하며 &lt;b&gt;최소한의 도로만&lt;/b&gt; 남겨둔다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A-B 직행값이 A에서 B로 가는 최단경로일때에만 남겨둠.&lt;/li&gt;
&lt;li&gt;전체 결과값의 A-B 도로 비용을 추가.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아니라면 그냥 넘어간다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플로이드 워셜을 &quot;활용&quot;하는 문제라고 할 수 있겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 코드&lt;/h3&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;&quot;&quot;&quot;
1. 최단 경로 그래프인지 확인
2. 아니라면 -1, 맞다면 다음 단계로
3. 플로이드 워셜 수행 -&amp;gt; 최단 거리값 업데이트는 X
4. A - C 도로를 검사할때, A - B - C 값과 A - C 값이 같다면 필요한 도로가 아니인 셈이므로 넘어감.
5. 모든 B를 거친 후 필요한 도로로 판정되면 결과값에 추가
&quot;&quot;&quot;

# 메모리: 32412KB / 시간: 40ms
from sys import stdin


input = stdin.readline

N = int(input())
graph = [list(map(int, input().split())) for _ in range(N)]

# 최단 경로 그래프가 아니라면 -1 반환
def checking():
    for k in range(N):
        for i in range(N):
            for j in range(N):
                # 우회하는 방법이 더 효율적이라면 최단 경로 그래프가 아닌셈
                if graph[i][k] + graph[k][j] &amp;lt; graph[i][j]:
                    return False
    return True


if not checking():
    print(-1)
    exit()

time = 0

for i in range(N):
    for j in range(i+1, N):
        flag = True

        for k in range(N):
            # 경유지가 출발지 or 도착지가 아니고, 우회해서 도착하는 값과 일직선 도로의 값이 같다면
            # =&amp;gt; 일직선 도로는 굳이 존재할 필요가 없음
            if k != i and k != j and graph[i][k] + graph[k][j] == graph[i][j]:
                flag = False
                break

        if flag:
            time += graph[i][j]


print(time)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 최소신장트리(MST)값을 구하면 되지 않나? 싶어서 도전해봤는데 실패했다.&lt;br /&gt;조금 더 생각해보니 당연한 문제였음.&lt;br /&gt;만약 노드 A, B, C, D의 간선이 아래와 같이 구성되어있다고 가정해보자.&lt;/p&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;A-B = 1
A-D = 2

B-C = 1
C-D = 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MST를 구하게 되면 (A-B, B-C, C-D) 순으로 이어지겠다. 이 경우 A-D의 값은 3이 된다.&lt;br /&gt;하지만 실제로 A-D의 최단경로는 2이다. 헉!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;결론적으론 삽질의 시간이었지만, 막연하게 '이런 문제는 무조건 플로이드 워셜이야~'하는것보단 낫다.&lt;/p&gt;</description>
      <category>  Algorithm/  Baekjoon</category>
      <category>python</category>
      <category>궁금한 민호 파이썬</category>
      <category>그래프 이론</category>
      <category>백준</category>
      <category>백준 궁금한 민호</category>
      <category>백준 파이썬</category>
      <category>최단경로</category>
      <category>플로이드워셜</category>
      <author>miwat</author>
      <guid isPermaLink="true">https://5as2s.tistory.com/388</guid>
      <comments>https://5as2s.tistory.com/388#entry388comment</comments>
      <pubDate>Wed, 24 Sep 2025 15:56:44 +0900</pubDate>
    </item>
    <item>
      <title>[백준/Python]11562: 백양로 브레이크</title>
      <link>https://5as2s.tistory.com/387</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/11562&quot;&gt;https://www.acmicpc.net/problem/11562&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준 문제집 - 0x1C강 - 플로이드 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;알고리즘: 그래프 이론, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;최단 경로&lt;/span&gt;, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;플로이드-워셜&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1471&quot; data-origin-height=&quot;1362&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boYV8Z/btsQHU2DZIN/pqi0Iz6nSJQAm4OtkScgFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boYV8Z/btsQHU2DZIN/pqi0Iz6nSJQAm4OtkScgFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boYV8Z/btsQHU2DZIN/pqi0Iz6nSJQAm4OtkScgFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboYV8Z%2FbtsQHU2DZIN%2Fpqi0Iz6nSJQAm4OtkScgFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1471&quot; height=&quot;1362&quot; data-origin-width=&quot;1471&quot; data-origin-height=&quot;1362&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 최단경로 문제와는 다르게 비용이 아닌 &lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&quot;일방통행&quot;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;이냐, &lt;b&gt;&lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;&quot;양방향&quot;&lt;/span&gt;&lt;/b&gt;이냐의 정보만 주어진다. &lt;b&gt;요 점이 포인트다.&lt;/b&gt;&lt;br /&gt;그리고 &quot;모든 길을 양방향으로 바꿨을경우 이동 불가능한 경로는 없다&quot;라고 되어있는데, &lt;b&gt;아예 이동 불가능한 길&lt;/b&gt;은 &lt;b&gt;양방향으로 바꿀 수 없다.&lt;/b&gt;&lt;br /&gt;a &amp;rarr; b든 b &amp;rarr; a든 &lt;b&gt;이미 일반통행이 존재했던 경우에만&lt;/b&gt; 양방향으로 바꿀 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;일반통행, 양방향, 막힌 길&lt;/span&gt;을 &lt;b&gt;&lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;별도로 표시&lt;/span&gt;&lt;/b&gt;해줘야한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;양방향 길(&lt;code&gt;b=1&lt;/code&gt;): 추가 비용 없이 양쪽 모두 이동 가능하므로 0&lt;/li&gt;
&lt;li&gt;일반통행 길(&lt;code&gt;b=0&lt;/code&gt;)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정방향: 추가 비용 0&lt;/li&gt;
&lt;li&gt;&lt;b&gt;역방향: 추가 비용 1(양방향으로 바꿔야 함)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;막힌 길: 이동 불가능(&lt;code&gt;INF&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분류해서 저장 후 플로이드 워셜을 수행하면 a &amp;rarr; b 이동 시 몇개의 길을 양방향으로 바꿔야하는지 구할 수 있다.&lt;br /&gt;만약 a &amp;rarr; b 사이에 공사 or 막힌 길이 없다면 0, 공사가 필요한 경우 역방향은 1로 저장해뒀으니 &lt;b&gt;그래프의 값&lt;/b&gt;이 곧 &lt;b&gt;공사 횟수&lt;/b&gt;인셈이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 코드&lt;/h3&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 메모리: 32412KB / 시간: 1152ms
from sys import stdin


input = stdin.readline
INF = int(1e9)

def main():
    # 건설되어 있는 도로(양방향, 일반도로 u -&amp;gt; v)라면 0으로 설정.
    # 일반 도로에서 역방향, v -&amp;gt; u의 값은 1로 설정한다.
    # =&amp;gt; 건설되지 않은 역방향 도로 v -&amp;gt; u가 최단거리에 포함되는 갯수 = 양방향 도로로 변경해야하는 도로의 갯수
    N, M = map(int, input().split())
    graph = [[INF if i != j else 0 for j in range(N)] for i in range(N)]

    for _ in range(M):
        u, v, b = map(int, input().split())
        graph[u-1][v-1] = 0

        if b == 1:
            graph[v-1][u-1] = 0
        else:
            graph[v-1][u-1] = 1

    for k in range(N):
        for i in range(N):
            for j in range(N):
                if graph[i][j] &amp;gt; graph[i][k] + graph[k][j]:
                    graph[i][j] = graph[i][k] + graph[k][j]

    K = int(input())
    ret = []
    for _ in range(K):
        s, e = map(int, input().split())
        print(graph[s-1][e-1])


main()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 어떻게 풀었는지 까먹었는데, 다시 풀다보니 기억났다... 글쓰기의 순기능이다.&lt;br /&gt;예전에 풀었던 문제들도 이따금씩 다시 풀어봐야겠다.&lt;/p&gt;</description>
      <category>  Algorithm/  Baekjoon</category>
      <category>python</category>
      <category>백양로 브레이크 백준</category>
      <category>백준</category>
      <category>백준 백양로 브레이크</category>
      <category>백준 파이썬</category>
      <category>최단경로</category>
      <category>플로이드워셜</category>
      <author>miwat</author>
      <guid isPermaLink="true">https://5as2s.tistory.com/387</guid>
      <comments>https://5as2s.tistory.com/387#entry387comment</comments>
      <pubDate>Sun, 21 Sep 2025 17:24:35 +0900</pubDate>
    </item>
    <item>
      <title>[백준/Python]1959: 운동</title>
      <link>https://5as2s.tistory.com/386</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1956&quot;&gt;https://www.acmicpc.net/problem/1956&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준 문제집 - 0x1C강 - 플로이드 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;알고리즘: 그래프 이론, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;최단 경로&lt;/span&gt;, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;플로이드-워셜&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buoh4q/btsQHBIWRGx/p7Ix2tt8VkVMZzfKcjNgZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buoh4q/btsQHBIWRGx/p7Ix2tt8VkVMZzfKcjNgZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buoh4q/btsQHBIWRGx/p7Ix2tt8VkVMZzfKcjNgZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbuoh4q%2FbtsQHBIWRGx%2Fp7Ix2tt8VkVMZzfKcjNgZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1472&quot; height=&quot;640&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;640&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;두 마을을 왕복&lt;/b&gt;하는 경우도 &lt;b&gt;사이클에 포함&lt;/b&gt;된다.&lt;br /&gt;즉, 플로이드 워셜로 각 마을 사이의 최단거리값을 구한 다음 한 마을을 기점으로 다른 마을까지의 왕복거리를 계산하면 된다.&lt;br /&gt;시작마을 A, 도착마을 B일때 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;A &amp;rarr; B의 값 + B &amp;rarr; A의 값이 가장 작은 경우&lt;/span&gt;를 선택하면 되는 것이다. (&lt;b&gt;일방통행&lt;/b&gt;이므로 A-B, B-A의 값이 다르다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 문제 자체는 어렵지 않다. 단순한 플로이드 워셜 문제에 가깝다.&lt;br /&gt;하지만 조건식을 어떻게 작성하는지에 따라 시간초과가 날 수도 있으니 주의해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체적인 과정은 아래와 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;각 마을 사이의 거리를 그래프에 저장. (a, b)쌍이 같은 도로가 여러번 주어지지 않음.&lt;/li&gt;
&lt;li&gt;플로이드 워셜 수행&lt;/li&gt;
&lt;li&gt;시작 마을 A를 기준으로 다른 마을 B까지의 왕복 거리들을 계산.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 짧은 거리가 결과값.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 코드&lt;/h3&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 메모리: 37660KB / 시간: 5832ms
from sys import stdin


input = stdin.readline
INF = float(&quot;inf&quot;)

def main():
    V, E = map(int, input().split())
    graph = [[INF] * V for _ in range(V)]

    for _ in range(E):
        a, b, c = map(int, input().split())
        graph[a-1][b-1] = c

    for k in range(V):
        for i in range(V):
            for j in range(V):
                if graph[i][j] &amp;gt; graph[i][k] + graph[k][j]:
                    graph[i][j] = graph[i][k] + graph[k][j]

    min_dis = INF

    for i in range(V):
        for j in range(i+1, V):
            if min_dis &amp;gt; graph[i][j] + graph[j][i]:
                min_dis = graph[i][j] + graph[j][i]

    print(min_dis if min_dis != INF else -1)


main()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 아래 코드는 &lt;span style=&quot;color: #ee2323;&quot;&gt;시간초과&lt;/span&gt;다.&lt;/p&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;from sys import stdin


input = stdin.readline
INF = float(&quot;inf&quot;)

def main():
    V, E = map(int, input().split())
    graph = [[INF] * (V+1) for _ in range(V+1)]

    for _ in range(E):
        a, b, c = map(int, input().split())
        graph[a][b] = c

    for k in range(1, V+1):
        for i in range(1, V+1):
            for j in range(1, V+1):
                graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j])

    min_dis = INF

    for i in range(1, V+1):
        for j in range(1, V+1):
            min_dis = min(min_dis, graph[i][j] + graph[j][i])

    print(min_dis if min_dis != INF else -1)


main()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⭐주요 차이점은 아래와 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;code&gt;min()&lt;/code&gt; 대신 &lt;code&gt;&amp;lt;, &amp;gt;&lt;/code&gt; 비교연산자 사용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;둘 다 덧셈연산 후 비교하는건 똑같음.&lt;/li&gt;
&lt;li&gt;하지만 &lt;code&gt;min()&lt;/code&gt;의 경우 참/거짓과 상관없이 무조건 &lt;b&gt;&quot;대입&quot;&lt;/b&gt;을 하게 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;리스트 크기 설정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;마을 번호는 1부터 시작되므로 그래프 저장 시 -1처리를 해주거나 리스트 크기를 &lt;code&gt;(V+1)&lt;/code&gt;로 설정해야함. (다만 이 문제에서의 결정적 포인트는 아니다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;마지막 for문의 범위 설정&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt; 이게 제일 중요하다고 생각한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문제에서 원하는 값은 &quot;거리&quot;값&lt;/b&gt;이지 &quot;어떤 마을&quot;인지가 중요한게 아니다.&lt;/li&gt;
&lt;li&gt;(AB, BA)값은 시작마을을 B로 설정했을때의 값(BA, AB)와도 같으므로, 순열이 아닌 &lt;b&gt;조합으로 판단&lt;/b&gt;해도 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 1번이 주요 포인트라고 생각했는데, 뭔가 이상해서 다시 돌려보니 3번이었다.&lt;br /&gt;중요도 순위는 3 &amp;gt; 1 &amp;gt;&amp;gt; 2 인듯 싶다...&lt;br /&gt;리스트 크기만 &lt;code&gt;V&lt;/code&gt;로 변경했을때는 똑같이 시간초과였고, &lt;b&gt;for문 범위 변경&lt;/b&gt; or &lt;b&gt;비교연산자 사용&lt;/b&gt; 중 하나만 적용해도 통과된다.&lt;/p&gt;</description>
      <category>  Algorithm/  Baekjoon</category>
      <category>python</category>
      <category>백준</category>
      <category>백준 운동</category>
      <category>백준 파이썬</category>
      <category>운동 파이썬</category>
      <category>최단 경로</category>
      <category>플로이드워셜</category>
      <author>miwat</author>
      <guid isPermaLink="true">https://5as2s.tistory.com/386</guid>
      <comments>https://5as2s.tistory.com/386#entry386comment</comments>
      <pubDate>Sat, 20 Sep 2025 19:48:07 +0900</pubDate>
    </item>
    <item>
      <title>[백준/Python]13168: 내일로 여행</title>
      <link>https://5as2s.tistory.com/375</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/13168&quot;&gt;https://www.acmicpc.net/problem/13168&lt;/a&gt;&lt;br /&gt;백준 문제집 - 0x1C강 - 플로이드 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;알고리즘: 구현, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;최단 경로&lt;/span&gt;, 해시를 사용한 집합과 맵, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;플로이드-워셜&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1475&quot; data-origin-height=&quot;1416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dxGOWa/btsPD2mZaPI/9Q5wS2RDv5pt7q1978x7g1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dxGOWa/btsPD2mZaPI/9Q5wS2RDv5pt7q1978x7g1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dxGOWa/btsPD2mZaPI/9Q5wS2RDv5pt7q1978x7g1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdxGOWa%2FbtsPD2mZaPI%2F9Q5wS2RDv5pt7q1978x7g1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1475&quot; height=&quot;1416&quot; data-origin-width=&quot;1475&quot; data-origin-height=&quot;1416&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 문자열 형태로 저장해야해서 그렇지, 문제 자체는 단순한 플로이드 워셜 문제다.&lt;br /&gt;&lt;b&gt;&lt;u&gt;다만 주의해야할 조건이 있다.&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;50% 할인 처리 시, 값이 실수형으로 나올 수 있으므로 미리 처리해줘야함.&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;방법 1: 실수형으로 계산 (&lt;code&gt;/&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;방법 2: 모든 비용을 2배로 취급 -&amp;gt; 50% 할인 시 정수형으로 처리됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;티켓을 중간에 구매할 경우&lt;/b&gt;도 따져야 함.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;시작도시-도착도시 값은 중복&lt;/b&gt;으로 주어질 수 있음. 최소비용으로 저장해야함.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 여행 도시가 M개라면 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;1 ~ M-1 번째에서 티켓을 구매할 경우를 고려&lt;/span&gt;해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 순서는 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;입력 데이터 처리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;[시작도시][도착도시] 값이 이미 존재한다면, 비교 후 &lt;b&gt;더 작은 값을 저장&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기본 값, 티켓 구입 시의 값&lt;/b&gt;을 &lt;b&gt;따로 분리&lt;/b&gt;하여 플로이드 워셜 수행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;양방향으로 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;기본 값(티켓 X) 총 비용 계산&lt;/li&gt;
&lt;li&gt;중간에 티켓을 구매했을 경우의 총 비용 계산
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1 ~ M-1번째 도시(인덱스 기준으로 0 ~ M-2)를 하나씩 체크&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;(i번째 도시까지 기본으로 이동한 값 + 티켓값)&lt;/span&gt; + &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;(i+1 ~ M번째 도시까지 티켓으로 이동한 값)&lt;/span&gt; 계산&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기존 계산값과 새로운 계산값을 매번 비교&lt;/b&gt;해가며 &lt;b&gt;최솟값 갱신&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;4번을 통해 얻은 최솟값(티켓 O)과, 기본 값을 비교
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;티켓을 사는게 더 효율적이라면 &quot;Yes&quot;, 아니면 &quot;No&quot; 출력&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 코드&lt;/h3&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 메모리: 33432KB / 시간: 720ms
from sys import stdin


input = stdin.readline
INF = int(1e9)

N, R = map(int, input().split())
R *= 2
data = set(input().rstrip().split())
cities = {d: i for i, d in enumerate(data)}

M = int(input())
trip_cities = [cities[city] for city in input().rstrip().split()]

#   그냥 정수 나눗셈 // 처리를 해주면 틀림...
# 해결방법 1. 실수형으로 계산, 2. 2배 해준뒤 // 사용
def calc(city, cost):
    if city in (&quot;Mugunghwa&quot;, &quot;ITX-Saemaeul&quot;, &quot;ITX-Cheongchun&quot;):
        return 0
    if city in (&quot;S-Train&quot;, &quot;V-Train&quot;):
        return cost // 2
    return cost


ticket = [[INF] * N for _ in range(N)]
normal = [[INF] * N for _ in range(N)]
K = int(input())

for _ in range(K):
    T, S, E, cost = input().rstrip().split()

    S, E = cities[S], cities[E]
    cost = int(cost) * 2

    ticket_cost = calc(T, cost)
    ticket[S][E] = min(ticket_cost, ticket[S][E])
    ticket[E][S] = min(ticket_cost, ticket[E][S])

    normal[S][E] = min(cost, normal[S][E])
    normal[E][S] = min(cost, normal[E][S])

for k in range(N):
    for i in range(N):
        for j in range(N):
            ticket[i][j] = min(ticket[i][k] + ticket[k][j], ticket[i][j])
            normal[i][j] = min(normal[i][k] + normal[k][j], normal[i][j])

# 티켓을 사지 않았을경우의 비용
normal_cost = sum(normal[trip_cities[i]][trip_cities[i+1]] for i in range(M-1))


# 중간에 티켓을 구매할 경우를 고려해서 계산해야함.
def total_cost(start, cost):
    for i in range(start, M-1):
        cost += ticket[trip_cities[i]][trip_cities[i+1]]

    return cost

min_cost = INF

curr_cost = 0
for start in range(M-1):
    cost = total_cost(start, curr_cost) + R
    min_cost = min(cost, min_cost)
    curr_cost += normal[trip_cities[start]][trip_cities[start+1]]

print(&quot;Yes&quot; if min_cost &amp;lt; normal_cost else &quot;No&quot;)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>  Algorithm/  Baekjoon</category>
      <category>python</category>
      <category>내일로 여행 파이썬</category>
      <category>백준</category>
      <category>백준 내일로 여행</category>
      <category>백준 파이썬</category>
      <category>최단 경로</category>
      <category>플로이드 워셜</category>
      <author>miwat</author>
      <guid isPermaLink="true">https://5as2s.tistory.com/375</guid>
      <comments>https://5as2s.tistory.com/375#entry375comment</comments>
      <pubDate>Thu, 31 Jul 2025 18:16:26 +0900</pubDate>
    </item>
    <item>
      <title>[백준/Python]17182: 우주 탐사선</title>
      <link>https://5as2s.tistory.com/373</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17182&quot;&gt;https://www.acmicpc.net/problem/17182&lt;/a&gt;&lt;br /&gt;백준 문제집 - 0x1C강 - 플로이드 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;알고리즘: &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;브루트포스 알고리즘&lt;/span&gt;, 최단 경로, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;비트마스킹&lt;/span&gt;, 백트래킹, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;플로이드-워셜&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1457&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/patRb/btsPAxBKYOL/e5uLffyre8CW3jb2TI04d0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/patRb/btsPAxBKYOL/e5uLffyre8CW3jb2TI04d0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/patRb/btsPAxBKYOL/e5uLffyre8CW3jb2TI04d0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpatRb%2FbtsPAxBKYOL%2Fe5uLffyre8CW3jb2TI04d0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1457&quot; height=&quot;636&quot; data-origin-width=&quot;1457&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;모든 행성을 탐사하는데&quot;&lt;/b&gt; 걸리는 최소 시간을 구해야한다.&lt;br /&gt;단, 출발지로 돌아올 필요는 없으며 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;이미 방문한 행성도 &quot;중복해서&quot; 갈 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;  위 조건때문에 &quot;최소 신장 트리&quot; 문제인 줄 알았으나 결정적인 차이가 있다!&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;한 번 방문한 곳은 따로 비용이 발생하지 않는 최소 신장 트리와 달리, &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;재방문이 가능하긴 하지만 비용이 발생&lt;/span&gt;하는 구조다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;따라서 &lt;b&gt;1) &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;플로이드 워셜&lt;/span&gt;로 각 행성간의 최단 경로를 구하고&lt;/b&gt;, &lt;b&gt;2) 방문하지 않은 행성들 중 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;현재 행성으로부터 소요 시간이 가장 짧은 행성을 선택&lt;/span&gt;&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 &lt;span style=&quot;background-color: #9feec3; color: #333333;&quot;&gt;DP(메모이제이션) + 비트마스킹&lt;/span&gt;을 적용하면 훨씬 빨라진다.&lt;br /&gt;&lt;code&gt;dp[curr][visited]&lt;/code&gt;: 현재 행성 &lt;code&gt;curr&lt;/code&gt;에서 시작해서, 아직 방문하지 않은 모든 행성을 탐사하는데 필요한 최소 시간&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;curr&lt;/code&gt;(현재 행성): 현재 탐사선이 위치한 행성 번호&lt;/li&gt;
&lt;li&gt;&lt;code&gt;visited&lt;/code&gt;(방문 상태): 지금까지 방문한 행성들을 나타내는 비트마스크&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 과정은 아래와 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;모든 간선 a-b를 대상으로 플로이드 워셜 수행&lt;/li&gt;
&lt;li&gt;출발 행성 방문체크 후, 기점으로 DFS 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 행성을 방문했다면 0 반환&lt;/li&gt;
&lt;li&gt;DP에 &lt;code&gt;[curr][visited]&lt;/code&gt;값이 있다면 해당 값 반환&lt;/li&gt;
&lt;li&gt;위 경우에 해당되지 않을 경우, 재귀적으로 DFS 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아직 방문하지 않은 행성들을 하나씩 선택&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; background-color: #f6e199;&quot;&gt;현재 행성-선택한 행성간의 거리값 + dfs(선택한 행성, 해당 행성을 방문처리한 visited)값&lt;/span&gt; 비교&lt;/li&gt;
&lt;li&gt;가장 최적의 값을 &lt;code&gt;dp[curr][visited]&lt;/code&gt;값으로 저장&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dp[curr][visited]&lt;/code&gt; 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 코드&lt;/h3&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 메모리: 32412KB / 시간: 44ms
from sys import stdin


input = stdin.readline
INF = int(1e9)

N, K = map(int, input().split())
graph = [list(map(int, input().split())) for _ in range(N)]

# 1. 플로이드-워셜로 두 행성간의 최단거리를 구해줌.
for k in range(N):
    for i in range(N):
        for j in range(N):
            graph[i][j] = min(graph[i][k] + graph[k][j], graph[i][j])

# 2. DP로 최적의 경로를 구함
# dp[curr][visited] = 현재 행성 curr에서 시작해서, 아직 방문하지 않은 모든 행성을 탐사하는데 필요한 최소 시간
dp = [[-1] * (1 &amp;lt;&amp;lt; N) for _ in range(N)]

def find(curr, visited):
    if visited == (1 &amp;lt;&amp;lt; N) - 1:
        return 0

    if dp[curr][visited] != -1:
        return dp[curr][visited]

    dp[curr][visited] = INF

    for nxt in range(N):
        # 방문하지 않은 행성일경우
        if not (visited &amp;amp; (1 &amp;lt;&amp;lt; nxt)):
            cost = graph[curr][nxt] + find(nxt, visited | (1 &amp;lt;&amp;lt; nxt))
            dp[curr][visited] = min(dp[curr][visited], cost)
    return dp[curr][visited]


print(find(K, 1 &amp;lt;&amp;lt; K))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 질문 게시판을 살펴보다가 발견한 글인데, &lt;b&gt;DP 이해에 도움이 될 것 같다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(&lt;span style=&quot;text-align: start;&quot;&gt;출처:&lt;/span&gt;&lt;a href=&quot;https://www.acmicpc.net/board/view/156743&quot;&gt;https://www.acmicpc.net/board/view/156743&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q.&lt;/b&gt; &quot;플로이드-워셜로 A &amp;rarr; C가 A &amp;rarr; B &amp;rarr; C로 갱신되었는데, A에서 시작해서 C를 방문한다면 A -&amp;gt; B -&amp;gt; C를 방문한 것이 되는데... 왜 B를 따로 방문처리 해줘야 하나요?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A.&lt;/b&gt; 구현 방식에 따라 차이가 있을것 같지만&lt;br /&gt;dp[현재행성][방문한 행성들] 과 같이 선언하고, 현재 행성에서 이동할 수 있는 다음행성들을 모두 바라보도록 했다면&lt;br /&gt;A &amp;rarr; B &amp;rarr; C로 실제로 이동했다고 해서 B를 고려하는 것은 불필요한 행동이라고 생각됩니다.&lt;br /&gt;모든 경우의 수를 바라보게 되면 A &amp;rarr; B 이동 B &amp;rarr; C 이동하는 경우가 있을테니깐요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문글 덕(?)에 나도 헷갈리는데... 결론은 플로이드 워셜에서의 A &amp;rarr; C 갱신(A&amp;rarr;B&amp;rarr;C)과 DP에서의 방문처리는 별개인 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 어차피 DP가 알아서 전체적으로 더 효율적인 최적의 값을 선택한다.&lt;/p&gt;</description>
      <category>  Algorithm/  Baekjoon</category>
      <category>python</category>
      <category>다이나믹 프로그래밍</category>
      <category>백준</category>
      <category>백준 우주 탐사선</category>
      <category>백준 파이썬</category>
      <category>비트마스킹</category>
      <category>우주 탐사선 파이썬</category>
      <category>플로이드 워셜</category>
      <author>miwat</author>
      <guid isPermaLink="true">https://5as2s.tistory.com/373</guid>
      <comments>https://5as2s.tistory.com/373#entry373comment</comments>
      <pubDate>Mon, 28 Jul 2025 16:32:23 +0900</pubDate>
    </item>
    <item>
      <title>[백준/Python]21940: 가운데에서 만나기</title>
      <link>https://5as2s.tistory.com/365</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/21940&quot;&gt;https://www.acmicpc.net/problem/21940&lt;/a&gt;&lt;br /&gt;백준 문제집 - 0x1C강 - 플로이드 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;알고리즘: 그래프 이론, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;최단 경로&lt;/span&gt;, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;플로이드-워셜&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1287&quot; data-origin-height=&quot;887&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hw7ST/btsOr3H20Kz/TakUhoxKHDj6G3YZkXta7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hw7ST/btsOr3H20Kz/TakUhoxKHDj6G3YZkXta7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hw7ST/btsOr3H20Kz/TakUhoxKHDj6G3YZkXta7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHw7ST%2FbtsOr3H20Kz%2FTakUhoxKHDj6G3YZkXta7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1287&quot; height=&quot;887&quot; data-origin-width=&quot;1287&quot; data-origin-height=&quot;887&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플로이드 워셜을 이용해 &lt;b&gt;왕복시간&lt;/b&gt;을 계산하는 문제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;문제 설명에 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;&quot;최대가 최소&quot;&lt;/span&gt;라고 되어있는데, 약간 불친절한 설명인듯...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;준형이와 친구들은 모두 다른 마을에 살고있다.&lt;br /&gt;따라서 어떤 마을 A에 대한 왕복시간은 모두 다르다.&lt;br /&gt;만약 A 마을의 왕복시간이 &lt;code&gt;[100, 10, 90, 110]&lt;/code&gt; 일경우, A 마을에 대한 왕복시간은 &lt;code&gt;110&lt;/code&gt;이 된다. &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;b&gt;(최대)&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;위 과정을 반복해서 1 ~ N 마을의 최대 왕복시간 리스트가 &lt;code&gt;[110, 90, 200, 100, 90]&lt;/code&gt;이 되었을때, X가 될 수 있는 마을은 2번, 5번 마을이다. &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;(최소)&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 처음 풀이할때는 딕셔너리를 사용해서 모든 마을의 왕복시간들을 저장했었고, 다시 풀이할때는 &lt;b&gt;리스트를 사용&lt;/b&gt;했는데 실행시간이 꽤 차이난다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 코드&lt;/h3&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 메모리: 33432KB / 시간: 924ms
from sys import stdin


input = stdin.readline
INF = int(1e9)

def main():
    def floyd_warshall(graph: list) -&amp;gt; list:
        for k in range(N):
            for i in range(N):
                for j in range(N):
                    graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j])
        return graph


    def calc() -&amp;gt; list[int]:
        &quot;&quot;&quot; X가 될 수 있는 마을 후보들 구하기 &quot;&quot;&quot;
        min_time = INF  # 최소 왕복시간
        towns = []  # X가 될 수 있는 마을들

        # 최대가 최소 = X까지 가는 왕복시간 중 최댓값이, 다른 마을로 가는 왕복시간들 중 최솟값인경우.
        for X in range(N):
            time = 0  # 현재 마을 기준 최대 왕복시간
            for curr in C:
                curr_time = graph[curr][X] + graph[X][curr]
                if curr_time == INF:
                    break
                time = max(time, curr_time)

            # 만약 다른 마을 왕복시간보다 작다면, 최솟값과 town 리스트 갱신.
            # 같다면 town 리스트에 현재 마을 추가
            if time &amp;lt; min_time:
                towns = [X]
                min_time = time
            elif time == min_time:
                towns.append(X)
        return towns


    N, M = map(int, input().split())
    graph = [[INF] * N for _ in range(N)]

    for i in range(N):
        graph[i][i] = 0

    for _ in range(M):
        A, B, T = map(int, input().split())
        graph[A-1][B-1] = T

    K = int(input())
    C = list(map(lambda x: int(x)-1, input().split()))

    graph = floyd_warshall(graph)
    towns = calc()

    print(&quot; &quot;.join(map(lambda x: str(x+1), towns)))


main()&lt;/code&gt;&lt;/pre&gt;</description>
      <category>  Algorithm/  Baekjoon</category>
      <category>python</category>
      <category>가운데에서 만나기 파이썬</category>
      <category>백준</category>
      <category>백준 가운데에서 만나기</category>
      <category>백준 파이썬</category>
      <category>최단거리</category>
      <category>플로이드워셜</category>
      <author>miwat</author>
      <guid isPermaLink="true">https://5as2s.tistory.com/365</guid>
      <comments>https://5as2s.tistory.com/365#entry365comment</comments>
      <pubDate>Sun, 8 Jun 2025 20:12:30 +0900</pubDate>
    </item>
    <item>
      <title>[백준/Python]14938: 서강그라운드</title>
      <link>https://5as2s.tistory.com/360</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/14938&quot;&gt;https://www.acmicpc.net/problem/14938&lt;/a&gt;&lt;br /&gt;백준 문제집 - 0x1C강 - 플로이드 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;알고리즘: 최단 경로, 데이크스트라, &lt;span style=&quot;background-color: #e1ff00; color: #333333;&quot;&gt;플로이드-워셜&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1541&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Thdn7/btsOhkoyZWn/BXlXoTa3KWX1dyDwKkUj0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Thdn7/btsOhkoyZWn/BXlXoTa3KWX1dyDwKkUj0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Thdn7/btsOhkoyZWn/BXlXoTa3KWX1dyDwKkUj0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FThdn7%2FbtsOhkoyZWn%2FBXlXoTa3KWX1dyDwKkUj0K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1536&quot; height=&quot;1541&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1541&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조건은 &lt;b&gt;한 지역으로 이동 후, 해당 노드로부터 &lt;u&gt;특정 거리 내에 위치&lt;/u&gt;한 아이템들만 주울 수 있다&lt;/b&gt;는것.&lt;br /&gt;따라서 &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;&lt;b&gt;1) 플로이드워셜 수행&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;background-color: #f6e199; color: #333333;&quot;&gt;&lt;b&gt;2) 노드를 하나 선택 후, 해당 노드로부터 다른 노드까지의 거리 체크&lt;/b&gt;&lt;/span&gt; 순서로 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 &lt;b&gt;자기 지역도 포함&lt;/b&gt;이므로, 이동한 지역(노드)의 아이템도 결과값에 더해줘야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 코드&lt;/h3&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 메모리: 33432KB / 시간: 328ms
from sys import stdin


input = stdin.readline
INF = float(&quot;inf&quot;)

n, m, r = map(int, input().split())
graph = [[INF] * n for _ in range(n)]

item = list(map(int, input().split()))

for i in range(n):
    graph[i][i] = 0

for _ in range(r):
    a, b, l = map(int, input().split())
    graph[a-1][b-1] = l
    graph[b-1][a-1] = l

# 플로이드-워셜 수행
# 한 노드에서 다른 모든 노드까지의 최단거리 구하기
for k in range(n):
    for i in range(n):
        for j in range(n):
            graph[i][j] = min(graph[i][k] + graph[k][j], graph[i][j])

max_get = 0

for target in range(n):
    get = 0

    for node in range(n):
        # 최단거리가 m 이하인 구역의 아이템만 주울 수 있음
        if graph[target][node] &amp;lt;= m:
            get += item[node]

    max_get = max(get, max_get)

print(max_get)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>  Algorithm/  Baekjoon</category>
      <category>python</category>
      <category>백준</category>
      <category>백준 서강그라운드</category>
      <category>백준 파이썬</category>
      <category>서강그라운드 파이썬</category>
      <category>플로이드워셜</category>
      <author>miwat</author>
      <guid isPermaLink="true">https://5as2s.tistory.com/360</guid>
      <comments>https://5as2s.tistory.com/360#entry360comment</comments>
      <pubDate>Wed, 28 May 2025 17:51:49 +0900</pubDate>
    </item>
  </channel>
</rss>