<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>동캄의 코딩도장</title>
    <link>https://dongkam.tistory.com/</link>
    <description>동캄의 코딩도장</description>
    <language>ko</language>
    <pubDate>Sun, 23 Aug 2026 18:21:34 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>동 캄</managingEditor>
    <image>
      <title>동캄의 코딩도장</title>
      <url>https://tistory1.daumcdn.net/tistory/5069744/attach/a51651d436944f888703e162e717a6e4</url>
      <link>https://dongkam.tistory.com</link>
    </image>
    <item>
      <title>백준 1261 [알고스팟] 파이썬</title>
      <link>https://dongkam.tistory.com/546</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1261&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1261&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757515526221&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 1261 알고스팟
# 목표: (0,0) &amp;rarr; (N-1, M-1)까지 이동할 때, 부숴야 하는 벽의 최소 개수를 구하는 문제
#       이동 시 빈 칸(0)은 비용 0, 벽(1)은 비용 1로 취급하여 다익스트라(우선순위 큐)로 해결

dr = [0, 0, -1, 1]  # 행 이동 (상하좌우)
dc = [1, -1, 0, 0]  # 열 이동 (상하좌우)

import sys, heapq
input = sys.stdin.readline

M, N = map(int, input().split())  # M=열, N=행 (주의: 문제에서 순서 반대)
field = []
for _ in range(N):
    # 미로 정보 입력 (0=빈 방, 1=벽)
    field.append(list(map(int, input().rstrip())))

# 우선순위 큐 (heapq 사용 &amp;rarr; 다익스트라)
# 원소 형태: (부순 벽 개수, 행, 열)
q = []

# 방문 여부 기록
visited = [[False for _ in range(M)] for _ in range(N)]

# 각 좌표까지 도달하는 최소 벽 부순 횟수 저장 배열
cnt = [[0 for _ in range(M)] for _ in range(N)]

# 시작점 (0,0)에서 출발, 부순 벽 개수 = 0
heapq.heappush(q, (0, 0, 0))
visited[0][0] = True

while q:
    wall_cnt, row, col = heapq.heappop(q)  # 현재 위치와 지금까지 부순 벽 개수
    
    for i in range(4):  # 상하좌우 탐색
        R = row + dr[i]
        C = col + dc[i]
        
        # 미로 범위 안에 있고, 아직 방문하지 않았다면
        if 0 &amp;lt;= R &amp;lt; N and 0 &amp;lt;= C &amp;lt; M and not visited[R][C]:
            visited[R][C] = True  # 방문 처리
            
            if field[R][C]:  # 벽(1)이라면
                # 벽을 하나 더 부숴야 하므로 비용 +1
                heapq.heappush(q, (wall_cnt + 1, R, C))
                cnt[R][C] = wall_cnt + 1
            else:  # 빈 방(0)이라면
                # 추가 비용 없이 그대로 진행
                heapq.heappush(q, (wall_cnt, R, C))
                cnt[R][C] = wall_cnt

# (N-1, M-1)에 도착했을 때 부순 벽의 최소 개수 출력
print(cnt[N-1][M-1])

# print(cnt)  # 전체 cnt 배열을 보고 싶으면 사용&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS인데 HEAPQ를 이용한 문제이다. (굳이 따지자면 다익스트라 알고리즘도 사용했다고 볼 수 있다.)&lt;/p&gt;</description>
      <category>코테/BOJ</category>
      <author>동 캄</author>
      <guid isPermaLink="true">https://dongkam.tistory.com/546</guid>
      <comments>https://dongkam.tistory.com/546#entry546comment</comments>
      <pubDate>Wed, 10 Sep 2025 23:45:53 +0900</pubDate>
    </item>
    <item>
      <title>백준 17835 [면접보는 승범이네] 파이썬</title>
      <link>https://dongkam.tistory.com/545</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17835&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/17835&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757430197930&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 17835 면접보는 승범이네
# 여러 개의 면접장을 시작점으로 하여, 모든 도시에서 가장 가까운 면접장까지의 최소 거리 계산
# 역방향 그래프 + 다익스트라 (다중 시작점)

import sys, heapq
input = sys.stdin.readline

# N: 도시 개수, M: 도로 개수, K: 면접장의 개수
N, M, K = map(int, input().split())

# dist[i] : i번 도시에서 가장 가까운 면접장까지의 최소 거리
dist = [float('inf') for _ in range(N + 1)]

# rev_costs[i] : 도시 i로 들어오는 간선 (역방향 그래프 저장)
rev_costs = [[] for _ in range(N + 1)]

# 도로 정보 입력 (A &amp;rarr; B, 비용 cost)
# 역방향 그래프로 저장 (B &amp;larr; A)
for _ in range(M):
    A, B, cost = map(int, input().split())
    rev_costs[B].append((A, cost))

# 다익스트라 (여러 시작점 가능)
def dijkstra(starts):
    q = []
    # 모든 면접장을 시작점으로 큐에 삽입
    for start in starts:
        dist[start] = 0
        heapq.heappush(q, (0, start))
    while q:
        d, curr_city = heapq.heappop(q)

        # 이미 더 짧은 경로가 있으면 무시
        if dist[curr_city] &amp;lt; d:
            continue

        # 현재 도시에서 갈 수 있는 역방향 간선 탐색
        for next_city, next_cost in rev_costs[curr_city]:
            # 더 짧은 거리 발견 시 갱신
            if dist[curr_city] + next_cost &amp;lt; dist[next_city]:
                dist[next_city] = dist[curr_city] + next_cost
                heapq.heappush(q, (dist[next_city], next_city))

# 면접장 도시 리스트 입력
targets = list(map(int, input().split()))

# 다익스트라 실행 (모든 면접장이 시작점)
dijkstra(targets)

# dist[1:] 중 최댓값을 갖는 도시 찾기
max_idx = dist.index(max(dist[1:]))

# 결과 출력: 가장 먼 도시 번호, 그 거리
print(max_idx)
print(dist[max_idx])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다익스트라 알고리즘을 사용하되, 역방향그래프를 이용하여 면접장을 시작점으로 하여 각 도시까지의 최단 거리를 구하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역방향 그래프+다익스트라알고리즘을 이용하면 N번돌리지않고, 1번만 돌리면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간복잡도는 Mlog(N)&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;a href=&quot;https://dongkam.tistory.com/543&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://dongkam.tistory.com/543&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1757430259905&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;백준 1238 [파티] 파이썬&quot; data-og-description=&quot;https://www.acmicpc.net/problem/1238 # 백준 1238 파티# N개의 마을, M개의 단방향 도로, 파티 장소 X# 각 학생이 자기 마을에서 X로 갔다가 다시 자기 마을로 돌아오는 데 걸리는# 왕복 최단 시간 중 최댓값을&quot; data-og-host=&quot;dongkam.tistory.com&quot; data-og-source-url=&quot;https://dongkam.tistory.com/543&quot; data-og-url=&quot;https://dongkam.tistory.com/543&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/u8SEr/hyZJcZFxgd/epMKJBuAeyUvFiPoIs4xk0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/oIz0G/hyZI06CLOY/yafJlep3jRthQUQWImyUSK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/criYId/hyZINMXokg/sv9NCLqawkiC64KcyaTyv1/img.jpg?width=1440&amp;amp;height=1440&amp;amp;face=0_0_1440_1440&quot;&gt;&lt;a href=&quot;https://dongkam.tistory.com/543&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://dongkam.tistory.com/543&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/u8SEr/hyZJcZFxgd/epMKJBuAeyUvFiPoIs4xk0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/oIz0G/hyZI06CLOY/yafJlep3jRthQUQWImyUSK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/criYId/hyZINMXokg/sv9NCLqawkiC64KcyaTyv1/img.jpg?width=1440&amp;amp;height=1440&amp;amp;face=0_0_1440_1440');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;백준 1238 [파티] 파이썬&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;https://www.acmicpc.net/problem/1238 # 백준 1238 파티# N개의 마을, M개의 단방향 도로, 파티 장소 X# 각 학생이 자기 마을에서 X로 갔다가 다시 자기 마을로 돌아오는 데 걸리는# 왕복 최단 시간 중 최댓값을&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;dongkam.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;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;</description>
      <category>코테/BOJ</category>
      <author>동 캄</author>
      <guid isPermaLink="true">https://dongkam.tistory.com/545</guid>
      <comments>https://dongkam.tistory.com/545#entry545comment</comments>
      <pubDate>Wed, 10 Sep 2025 00:05:13 +0900</pubDate>
    </item>
    <item>
      <title>백준 11779 [최소비용 구하기 2] 파이썬</title>
      <link>https://dongkam.tistory.com/544</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/11779&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/11779&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757428703292&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 11779 최소비용 구하기 2
# 다익스트라 알고리즘을 이용해 최소 비용과 경로를 찾는 문제

import sys, heapq

input = sys.stdin.readline

# 도시(정점) 개수 N
N = int(input())
# 버스(간선) 개수 M
M = int(input())

# dist[i] : 시작점에서 i번 도시까지의 최소 비용 저장
dist = [float('inf') for _ in range(N + 1)]
# routes[i] : 시작점에서 i번 도시까지 오는 경로 저장
routes = [[] for _ in range(N + 1)]
# costs[i] : i번 도시에서 출발하는 (도착 도시, 비용) 리스트
costs = [[] for _ in range(N + 1)]

# 버스 노선 입력 받기
for _ in range(M):
    A, B, cost = map(int, input().split())
    # A &amp;rarr; B 로 가는 비용 cost
    costs[A].append((B, cost))

# 시작 도시, 도착 도시 입력
start, end = map(int, input().split())

# 우선순위 큐 (최소 힙)
q = []
# 시작 도시까지의 최소 비용은 0
dist[start] = 0
# 시작 경로는 자기 자신만 포함
routes[start].append(start)
# (비용, 현재 도시) 형태로 푸시
heapq.heappush(q, (0, start))

# 다익스트라 알고리즘 수행
while q:
    d, curr_city = heapq.heappop(q)  # 현재 비용, 현재 도시 꺼내기

    # 이미 더 짧은 경로가 있다면 스킵
    if dist[curr_city] &amp;lt; d:
        continue

    # 현재 도시에서 이동할 수 있는 인접 도시 탐색
    for next_city, next_cost in costs[curr_city]:
        # 새로운 경로 비용이 더 적다면 업데이트
        if dist[curr_city] + next_cost &amp;lt; dist[next_city]:
            dist[next_city] = dist[curr_city] + next_cost
            # 우선순위 큐에 (새로운 비용, 다음 도시) 삽입
            heapq.heappush(q, (dist[next_city], next_city))
            # 경로 갱신 (깊은 복사 후 다음 도시 추가)
            routes[next_city] = routes[curr_city].copy()
            routes[next_city].append(next_city)

# 결과 출력
# 1) 최소 비용
print(dist[end])
# 2) 경로에 포함된 도시 개수
print(len(routes[end]))
# 3) 실제 경로
print(*routes[end])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다익스트라 알고리즘을 이용하되, 경로를 추적하는 조건을 더한 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N의 숫자가 작아 배열을 전체적으로 copy하여도 문제 없겠다고 판단하여 해결하였는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N이 더 큰 경우에서는 parent를 이용하면 메모리를 더 효율적으로 관리하여 해결할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1757428776890&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 11779 최소비용 구하기 2
# 다익스트라 + parent 배열을 이용한 경로 복원

import sys, heapq
input = sys.stdin.readline

N = int(input())   # 도시 개수
M = int(input())   # 버스 개수

dist = [float('inf')] * (N + 1)  # 최소 비용 저장
parent = [0] * (N + 1)           # 경로 추적용 parent
graph = [[] for _ in range(N + 1)]

# 그래프 입력
for _ in range(M):
    A, B, cost = map(int, input().split())
    graph[A].append((B, cost))

start, end = map(int, input().split())

# 다익스트라
pq = []
dist[start] = 0
heapq.heappush(pq, (0, start))

while pq:
    d, curr = heapq.heappop(pq)
    if dist[curr] &amp;lt; d:
        continue
    for nxt, cost in graph[curr]:
        if dist[curr] + cost &amp;lt; dist[nxt]:
            dist[nxt] = dist[curr] + cost
            parent[nxt] = curr  # nxt의 부모를 curr로 기록
            heapq.heappush(pq, (dist[nxt], nxt))

# 경로 복원
path = []
node = end
while node != 0:      # parent[시작점] = 0 이므로 여기서 종료
    path.append(node)
    node = parent[node]
path.reverse()

# 출력
print(dist[end])          # 최소 비용
print(len(path))          # 경로 길이
print(*path)              # 경로&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>코테/BOJ</category>
      <author>동 캄</author>
      <guid isPermaLink="true">https://dongkam.tistory.com/544</guid>
      <comments>https://dongkam.tistory.com/544#entry544comment</comments>
      <pubDate>Tue, 9 Sep 2025 23:40:37 +0900</pubDate>
    </item>
    <item>
      <title>백준 1238 [파티] 파이썬</title>
      <link>https://dongkam.tistory.com/543</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1238&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1238&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757256833473&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 1238 파티
# N개의 마을, M개의 단방향 도로, 파티 장소 X
# 각 학생이 자기 마을에서 X로 갔다가 다시 자기 마을로 돌아오는 데 걸리는
# 왕복 최단 시간 중 최댓값을 구하는 문제

import sys, heapq

input = sys.stdin.readline
N, M, X = map(int, input().split())

# dist[i][j] = i에서 j까지의 최단 거리
dist = [[float('inf') for _ in range(N+1)] for _ in range(N+1)]
# costs[u] = (가중치, v) 형식으로 u &amp;rarr; v 간선 저장
costs = [[] for _ in range(N+1)]

# 도로 정보 입력
for _ in range(M):
    A, B, cost = map(int, input().split())
    costs[A].append((cost, B))

# 다익스트라 함수: start에서 다른 모든 노드까지 최단 거리 계산
def dijkstra(start):
    dist[start][start] = 0   # 자기 자신까지의 거리는 0
    q = []
    heapq.heappush(q, (0, start))  # (누적 비용, 현재 노드)

    while q:
        cost, curr = heapq.heappop(q)
        # 이미 더 짧은 거리로 방문한 적 있으면 무시
        if dist[start][curr] &amp;lt; cost:
            continue
        # 인접 노드 확인
        for next_cost, nxt in costs[curr]:
            new_dist = dist[start][curr] + next_cost
            # 더 짧은 경로 발견 시 갱신 (Relaxation)
            if new_dist &amp;lt; dist[start][nxt]:
                dist[start][nxt] = new_dist
                heapq.heappush(q, (new_dist, nxt))

# 모든 노드에서 출발하는 다익스트라 실행
for i in range(1, N+1):
    dijkstra(i)

# 정답 계산
# i번째 학생이 X로 가는 최단거리(dist[i][X]) + 돌아오는 최단거리(dist[X][i])
# 그 중 최댓값
ans = 0
for i in range(1, N+1):
    ans = max(dist[X][i] + dist[i][X], ans)

print(ans)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간복잡도와 공간복잡도를 고려했을때, i번째집-&amp;gt;파티장-&amp;gt;i번째집으로 이동하는 경로를 구하기위해 다익스트라를 N번해도 문제가없을거라 생각해서 다익스트라를 N번 돌렸다. 통과했다.&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;하지만, GPT가 역방향 다익스트라를 제시했고 이는 다익스트라 2번으로 해결된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757257397829&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import sys, heapq

input = sys.stdin.readline
N, M, X = map(int, input().split())

# 원래 그래프와 역방향 그래프를 저장할 인접 리스트
graph = [[] for _ in range(N + 1)]
rev_graph = [[] for _ in range(N + 1)]

# 그래프 입력 받기 (원래 그래프와 역방향 그래프 동시 생성)
for _ in range(M):
    A, B, cost = map(int, input().split())
    graph[A].append((cost, B))
    rev_graph[B].append((cost, A))

def dijkstra(start, adj_list):
    dist = [float('inf')] * (N + 1)
    dist[start] = 0
    q = [(0, start)]

    while q:
        cost, curr = heapq.heappop(q)
        if dist[curr] &amp;lt; cost:
            continue
        for next_cost, next_node in adj_list[curr]:
            new_dist = cost + next_cost
            if new_dist &amp;lt; dist[next_node]:
                dist[next_node] = new_dist
                heapq.heappush(q, (new_dist, next_node))
    return dist

# 1. 파티장에서 각 학생의 집으로 돌아가는 최단 거리 (X -&amp;gt; i)
dist_to_home = dijkstra(X, graph)

# 2. 각 학생의 집에서 파티장으로 가는 최단 거리 (i -&amp;gt; X)
#    이는 역방향 그래프에서 X를 시작점으로 하는 최단 거리와 동일
dist_to_party = dijkstra(X, rev_graph)

ans = 0
for i in range(1, N + 1):
    total_dist = dist_to_home[i] + dist_to_party[i]
    ans = max(ans, total_dist)

print(ans)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 파티장 -&amp;gt; i번째 집 이동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -이는 기존과 같이 다익스트라를 이용하여 구하면 된다.&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;2. i번째 집 -&amp;gt; 파티장 이동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - 우리가 궁금한 것은 i번째 집에서 파티장까지 이동하는 최소 거리이다. 반대로 생각하면 파티장에서 i번째 집까지 이동한다고 생각하고, 단방향 그래프를 뒤집어서 다익스트라를 이용할 수 있다.&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;</description>
      <category>코테/BOJ</category>
      <author>동 캄</author>
      <guid isPermaLink="true">https://dongkam.tistory.com/543</guid>
      <comments>https://dongkam.tistory.com/543#entry543comment</comments>
      <pubDate>Mon, 8 Sep 2025 00:05:09 +0900</pubDate>
    </item>
    <item>
      <title>백준 16638 [괄호 추가하기 2] 파이썬</title>
      <link>https://dongkam.tistory.com/542</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/16638&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/16638&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1756906967962&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 16638 괄호 추가하기2
import sys

sys.setrecursionlimit(10**9)  # 재귀 깊이를 충분히 늘려줌 (최대 10억)
input = sys.stdin.readline

N = int(input())  # 수식의 길이 (숫자 + 연산자 개수 포함)
ans = float(&quot;-inf&quot;)  # 최댓값을 저장할 변수 (음수도 나올 수 있으므로 -inf로 초기화)

expression = list(
    map(str, input())
)  # 수식을 문자열 리스트로 저장 (예: &quot;1+2*3&quot; -&amp;gt; ['1','+','2','*','3'])

nums = []  # 숫자들만 저장할 리스트
opers = []  # 연산자들만 저장할 리스트

# 수식에서 숫자와 연산자를 분리
# 짝수 인덱스 -&amp;gt; 숫자, 홀수 인덱스 -&amp;gt; 연산자
for i in range(N):
    if i % 2 == 0:
        nums.append(int(expression[i]))
    else:
        opers.append(expression[i])

len_oper = len(opers)  # 연산자의 개수


def calcul(depth, curr, prev_bracket):
    &quot;&quot;&quot;
    depth: 현재 고려 중인 연산자의 인덱스
    curr: 괄호로 묶은 연산자의 인덱스들을 문자열로 저장 (예: &quot;02&quot; &amp;rarr; 0번째, 2번째 연산자에 괄호 있음)
    prev_bracket: 직전 연산자에 괄호를 쳤는지 여부 (겹치는 괄호 방지)
    &quot;&quot;&quot;
    global ans
    global len_oper

    # 연산자들을 전부 검사한 경우 (괄호를 어디에 칠지 결정이 끝남)
    if depth == len_oper:
        del_ind = []  # 괄호 처리한 연산자의 인덱스를 기록
        temp_nums = nums.copy()  # 원본 배열 훼손 방지
        temp_opers = opers.copy()

        # 괄호로 묶은 연산자가 있으면 먼저 처리
        if curr:
            bracket_ind = list(map(int, curr))  # 문자열 curr &amp;rarr; int 리스트 변환
            for ind in bracket_ind:
                # 해당 연산자를 먼저 계산하여 temp_nums에 반영
                if temp_opers[ind] == &quot;+&quot;:
                    temp_nums[ind] = temp_nums[ind] + temp_nums[ind + 1]
                elif temp_opers[ind] == &quot;-&quot;:
                    temp_nums[ind] = temp_nums[ind] - temp_nums[ind + 1]
                elif temp_opers[ind] == &quot;*&quot;:
                    temp_nums[ind] = temp_nums[ind] * temp_nums[ind + 1]

                del_ind.append(ind)  # 나중에 해당 연산자와 숫자를 제거해야 하므로 기록

            # 괄호 처리한 연산자/숫자를 제거
            while del_ind:
                del_i = del_ind.pop()
                temp_nums.pop(del_i + 1)  # 오른쪽 숫자 제거
                temp_opers.pop(del_i)  # 해당 연산자 제거

        # 곱셈 먼저 처리 (*는 우선순위가 높음)
        temp_oper_len = len(temp_opers)
        i = 0
        while i &amp;lt; temp_oper_len:
            if temp_opers[i] == &quot;*&quot;:
                temp_nums[i] = temp_nums[i] * temp_nums[i + 1]
                temp_nums.pop(i + 1)  # 오른쪽 숫자 제거
                temp_opers.pop(i)  # 연산자 제거
                temp_oper_len -= 1
            else:
                i += 1

        # 남은 연산자들은 왼쪽부터 순서대로 계산 (+, - 만 남음)
        cal_ans = temp_nums[0]
        for i in range(len(temp_opers)):
            if temp_opers[i] == &quot;+&quot;:
                cal_ans += temp_nums[i + 1]
            elif temp_opers[i] == &quot;-&quot;:
                cal_ans -= temp_nums[i + 1]
            elif temp_opers[i] == &quot;*&quot;:
                cal_ans *= temp_nums[i + 1]

        # 최댓값 갱신
        ans = max(ans, cal_ans)
        return

    else:
        # 직전 연산자를 괄호로 묶었다면 이번 연산자는 괄호 불가 (겹치면 안 됨)
        if prev_bracket:
            calcul(depth + 1, curr, False)
        else:
            # 현재 연산자에 괄호를 치는 경우
            calcul(depth + 1, curr + str(depth), True)
            # 현재 연산자에 괄호를 안 치는 경우
            calcul(depth + 1, curr, False)


# 탐색 시작 (0번째 연산자부터, 괄호 없음 상태)
calcul(0, &quot;&quot;, False)

# 최댓값 출력
print(ans)&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;괄호 추가하기 1 문제를 풀고나서 조건 하나만 더 추가해주면 되었다.&lt;/p&gt;</description>
      <category>코테/BOJ</category>
      <author>동 캄</author>
      <guid isPermaLink="true">https://dongkam.tistory.com/542</guid>
      <comments>https://dongkam.tistory.com/542#entry542comment</comments>
      <pubDate>Wed, 3 Sep 2025 22:43:21 +0900</pubDate>
    </item>
    <item>
      <title>백준 16637 [괄호 추가하기] 파이썬</title>
      <link>https://dongkam.tistory.com/541</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/16637&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/16637&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1756900086783&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 16637 괄호 추가하기
import sys

sys.setrecursionlimit(10**9)  # 재귀 깊이를 충분히 늘려줌 (최대 10억)
input = sys.stdin.readline

N = int(input())  # 수식의 길이 (숫자 + 연산자)
ans = float(&quot;-inf&quot;)  # 최댓값을 저장할 변수 (음수도 나올 수 있으므로 -inf로 초기화)

expression = list(map(str, input()))  # 수식을 문자열 리스트로 저장

nums = []  # 숫자들만 따로 저장할 리스트
opers = []  # 연산자들만 따로 저장할 리스트

# 인덱스가 짝수면 숫자, 홀수면 연산자
for i in range(N):
    if i % 2 == 0:
        nums.append(int(expression[i]))
    else:
        opers.append(expression[i])

len_oper = len(opers)  # 연산자의 개수


def calcul(depth, curr, prev_bracket):
    &quot;&quot;&quot;
    depth: 현재 고려 중인 연산자의 인덱스
    curr: 괄호로 묶은 연산자의 인덱스들을 문자열로 저장
    prev_bracket: 직전 연산자를 괄호로 묶었는지 여부 (겹치는 괄호 방지용)
    &quot;&quot;&quot;
    global ans
    global len_oper

    # 모든 연산자에 대해 괄호 선택 여부를 결정한 경우
    if depth == len_oper:
        del_ind = []  # 괄호 친 연산자의 인덱스 저장
        temp_nums = nums.copy()  # 원본 훼손 방지를 위해 복사
        temp_opers = opers.copy()

        # curr에 괄호 처리할 연산자의 인덱스가 들어있다면 실행
        if curr:
            bracket_ind = list(map(int, curr))  # 괄호 인덱스를 int로 변환
            for ind in bracket_ind:
                # 해당 연산자를 먼저 계산하여 숫자 배열에 반영
                if temp_opers[ind] == &quot;+&quot;:
                    temp_nums[ind] = temp_nums[ind] + temp_nums[ind + 1]
                elif temp_opers[ind] == &quot;-&quot;:
                    temp_nums[ind] = temp_nums[ind] - temp_nums[ind + 1]
                elif temp_opers[ind] == &quot;*&quot;:
                    temp_nums[ind] = temp_nums[ind] * temp_nums[ind + 1]

                del_ind.append(ind)  # 나중에 삭제할 연산자 인덱스 기록

            # 괄호로 처리한 연산자와 숫자 제거
            while del_ind:
                del_i = del_ind.pop()
                temp_nums.pop(del_i + 1)  # 오른쪽 숫자 제거
                temp_opers.pop(del_i)  # 해당 연산자 제거

        # 괄호 처리가 끝난 후, 왼쪽부터 순차적으로 계산
        cal_ans = temp_nums[0]
        for i in range(len(temp_opers)):
            if temp_opers[i] == &quot;+&quot;:
                cal_ans += temp_nums[i + 1]
            elif temp_opers[i] == &quot;-&quot;:
                cal_ans -= temp_nums[i + 1]
            elif temp_opers[i] == &quot;*&quot;:
                cal_ans *= temp_nums[i + 1]

        # 최댓값 갱신
        ans = max(ans, cal_ans)
        return

    else:
        # 직전에 괄호를 쳤다면 현재 연산자는 괄호 불가 (겹치면 안 됨)
        if prev_bracket:
            calcul(depth + 1, curr, False)
        # 괄호를 칠 수 있는 경우
        elif depth &amp;lt; len_oper:
            # 현재 연산자에 괄호를 치는 경우
            calcul(depth + 1, curr + str(depth), True)
            # 현재 연산자에 괄호를 안 치는 경우
            calcul(depth + 1, curr, False)


# 0번째 연산자부터 시작, curr은 빈 문자열, 아직 괄호 안 친 상태
calcul(0, &quot;&quot;, False)

# 결과 출력
print(ans)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거창한 알고리즘이 있는줄 알았는데, 브루트포스 문제였다.&lt;/p&gt;</description>
      <category>코테/BOJ</category>
      <author>동 캄</author>
      <guid isPermaLink="true">https://dongkam.tistory.com/541</guid>
      <comments>https://dongkam.tistory.com/541#entry541comment</comments>
      <pubDate>Wed, 3 Sep 2025 20:48:22 +0900</pubDate>
    </item>
    <item>
      <title>백준 16719 [ZOAC] 파이썬</title>
      <link>https://dongkam.tistory.com/540</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/16719&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/16719&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;/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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1756020628871&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 16719 ZOAC

import sys

sys.setrecursionlimit(10**6)
input = sys.stdin.readline

strings = list(map(str, input().rstrip()))


def like_zoac(string, prev_print, next_print):
    print_str = min(string)
    idx = string.index(print_str)
    print(prev_print + print_str + next_print)
    prev_string = string[:idx]
    if len(string) - 1 != idx:
        next_string = string[idx + 1 :]
    else:
        next_string = &quot;&quot;

    if next_string:
        next_strings = like_zoac(next_string, prev_print + string[idx], next_print)
        next_strings = next_strings[1:]
    else:
        next_strings = next_print

    if prev_string:
        like_zoac(prev_string, prev_print, string[idx] + next_strings)

    return prev_print + string[idx] + next_strings


like_zoac(strings, &quot;&quot;, &quot;&quot;)&lt;/code&gt;&lt;/pre&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;pre id=&quot;code_1756020646548&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 16719 ZOAC

import sys

input = sys.stdin.readline

s = list(input().rstrip())
n = len(s)


def solve(l, r, acc):
    if l &amp;gt;= r:
        return
    # 현재 구간 [l, r) 에서 사전순 최소 문자를 찾음
    idx = min(range(l, r), key=lambda i: s[i])
    acc[idx] = s[idx]
    print(&quot;&quot;.join(acc))
    # 오른쪽 먼저
    solve(idx + 1, r, acc)
    # 왼쪽 나중
    solve(l, idx, acc)


acc = [&quot;&quot;] * n
solve(0, n, acc)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPT 풀이를 첨부한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진짜 열받네&lt;/p&gt;</description>
      <category>코테/BOJ</category>
      <author>동 캄</author>
      <guid isPermaLink="true">https://dongkam.tistory.com/540</guid>
      <comments>https://dongkam.tistory.com/540#entry540comment</comments>
      <pubDate>Sun, 24 Aug 2025 16:30:55 +0900</pubDate>
    </item>
    <item>
      <title>백준 1368 [물대기] 파이썬</title>
      <link>https://dongkam.tistory.com/539</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1368&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1368&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1756014444861&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 1368 물대기
# 문제 요약: 
# 각 논에 직접 우물을 팔거나, 다른 논에서 물을 끌어올 수 있다.
# 모든 논이 물을 공급받을 때 최소 비용을 구하는 문제.
# 풀이 아이디어: 
# &quot;우물&quot;을 가상의 0번 노드로 두고, 우물 &amp;harr; 각 논의 비용(dig_costs)을 간선으로 생각.
# 그리고 논 &amp;harr; 논 간의 물길 비용(recv_costs)도 간선으로 생각해서 MST를 구한다.
# 여기서는 Prim 알고리즘을 사용.

import sys
import heapq

input = sys.stdin.readline
N = int(input())  # 논의 개수

dig_costs = []    # dig_costs[i] = i번 논에 우물을 직접 파는 비용
recv_costs = []   # recv_costs[i][j] = i번 논에서 j번 논으로 물을 끌어오는 비용
visited = [False for _ in range(N + 1)]  # 각 논의 방문 여부 (0은 가상의 우물 노드)

# 각 논에 우물 파는 비용 입력
for _ in range(N):
    dig_costs.append(int(input()))

# 논 사이의 물길 비용 입력
for _ in range(N):
    recv_costs.append(list(map(int, input().split())))

# 우물을 팔 수 있는 모든 선택지를 우선순위 큐(힙)에 넣음
# (비용, 논 번호)
# &amp;rarr; 이는 &quot;가상의 우물 노드(0)에서 각 논으로 가는 간선&quot;을 추가하는 효과
q = []
for i in range(N):
    heapq.heappush(q, (dig_costs[i], i + 1))

cnt = 0  # 물 공급된 논 개수
ans = 0  # 최소 비용 합

# Prim 알고리즘 시작
while q and cnt &amp;lt; N:
    cost, node = heapq.heappop(q)
    
    # 이미 물이 공급된 논이면 스킵
    if visited[node]:
        continue

    # 새로운 논에 물 공급
    visited[node] = True
    ans += cost
    cnt += 1

    # 현재 논에서 다른 논으로 물길을 연결하는 간선 후보들을 힙에 추가
    for nxt in range(1, N + 1):
        if not visited[nxt]:
            heapq.heappush(q, (recv_costs[node - 1][nxt - 1], nxt))

# 모든 논에 물 공급이 끝났으므로 최소 비용 출력
print(ans)&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;p data-ke-size=&quot;size16&quot;&gt;결국 GPT의 도움을 받았는데, 풀이를 보니 너무 허무했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 우물도 heapq에 넣으면 그만이었다. (그래야 Prim 알고리즘이 정확히 동작)&lt;/p&gt;</description>
      <category>코테/BOJ</category>
      <author>동 캄</author>
      <guid isPermaLink="true">https://dongkam.tistory.com/539</guid>
      <comments>https://dongkam.tistory.com/539#entry539comment</comments>
      <pubDate>Sun, 24 Aug 2025 14:48:14 +0900</pubDate>
    </item>
    <item>
      <title>백준 1774 [우주신과의 교감] 파이썬</title>
      <link>https://dongkam.tistory.com/538</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1774&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1774&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1755958136833&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 1774 우주신과 교감
# 최소 스패닝 트리(MST, Kruskal 알고리즘) 활용
# - N개의 좌표(우주신)와 M개의 이미 연결된 통로가 주어짐
# - 나머지를 최소 비용으로 연결하는 거리 합 구하기

import sys
import math
input = sys.stdin.readline

N, M = map(int, input().split())  # N = 우주신 수, M = 이미 연결된 통로 수
ans = 0                           # 최종 결과(연결 비용 합)
pos = [[0, 0]]                    # 1-based indexing을 위해 더미 좌표 추가

# 유니온-파인드 parent 초기화
parent = [i for i in range(N + 1)]

def find(x):
    &quot;&quot;&quot;루트 노드 찾기 (경로 압축 적용)&quot;&quot;&quot;
    if x != parent[x]:
        parent[x] = find(parent[x])
    return parent[x]

def union(a, b):
    &quot;&quot;&quot;두 노드를 합치기 (사이클 방지)&quot;&quot;&quot;
    a = find(a)
    b = find(b)
    if a != b:             # 다른 집합일 때만 합침
        parent[a] = b
        return True
    return False

# 1. 좌표 입력 받기
for _ in range(N):
    pos.append(list(map(int, input().split())))

# 2. 이미 연결된 M개의 간선 union 처리
for _ in range(M):
    A, B = map(int, input().split())
    union(A, B)

# 3. 모든 가능한 간선(거리) 계산
costs = []
for i in range(1, N + 1):
    for j in range(i + 1, N + 1):   # i &amp;lt; j로 최적화 가능 (중복 제거)
        pos_i_x, pos_i_y = pos[i]
        pos_j_x, pos_j_y = pos[j]
        cost = math.sqrt((pos_i_x - pos_j_x) ** 2 + (pos_i_y - pos_j_y) ** 2)
        costs.append((i, j, cost))

# 4. 거리 기준으로 간선 정렬
costs.sort(key=lambda x: x[2])

# 5. 크루스칼 알고리즘 실행
for a, b, c in costs:
    if union(a, b):     # 연결되지 않은 노드라면 MST에 포함
        ans += c

# 6. 결과 출력 (소수점 둘째 자리까지)
print(&quot;{:.2f}&quot;.format(ans))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막에 소수점 둘째 자리까지 출력이 생각이 안났다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외에는 무난한 MST 문제&lt;/p&gt;</description>
      <category>코테/BOJ</category>
      <author>동 캄</author>
      <guid isPermaLink="true">https://dongkam.tistory.com/538</guid>
      <comments>https://dongkam.tistory.com/538#entry538comment</comments>
      <pubDate>Sat, 23 Aug 2025 23:09:19 +0900</pubDate>
    </item>
    <item>
      <title>백준 13418 [학교 탐방하기] 파이썬</title>
      <link>https://dongkam.tistory.com/537</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/13418&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/13418&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1755954646225&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 13418 학교 탐방하기
# 최소 스패닝 트리를 두 번 구해서 (최선/최악의 경우) 차이를 계산하는 문제
# - 좋은 길(C=0, 오르막길)은 피로도를 증가시킴
# - 나쁜 길(C=1, 내리막길)은 피로도를 증가시키지 않음
# 피로도 = (오르막길 개수)^2 이므로, MST를 두 번 구성해야 함

import sys
input = sys.stdin.readline

N, M = map(int, input().split())  # 건물 개수 N, 간선(길) 개수 M

# 유니온-파인드(Disjoint Set Union) 함수 정의
def find(x):
    &quot;&quot;&quot;루트 노드를 찾는 함수 (경로 압축)&quot;&quot;&quot;
    if x != parent[x]:
        parent[x] = find(parent[x])
    return parent[x]

def union(a, b):
    &quot;&quot;&quot;두 노드를 합치는 함수 (다른 집합일 때만 합침)&quot;&quot;&quot;
    a = find(a)
    b = find(b)
    if a != b:
        parent[a] = b
        return True
    return False


# 간선 정보 입력 (M+1개, 0번째는 입구와 1번 건물 연결)
routes = []
for _ in range(M + 1):
    routes.append(list(map(int, input().split())))  # A, B, C(0=오르막, 1=내리막)


# -------------------------------
# 1) 최선(best case): 오르막길을 최소화하는 경우
#    =&amp;gt; 내리막길(1)을 우선적으로 선택해야 하므로
#       내림차순 정렬 (C=1이 앞으로 오도록 정렬)
# -------------------------------
parent = [i for i in range(N + 1)]
best_ans = 0  # 선택된 오르막길 개수

routes.sort(key=lambda x: -x[2])  # C=1(내리막)이 앞으로 오게 정렬
for A, B, C in routes:
    if union(A, B):       # 사이클을 만들지 않는 경우만 선택
        if C == 0:        # 오르막길이면 카운트 증가
            best_ans += 1


# -------------------------------
# 2) 최악(worst case): 오르막길을 최대화하는 경우
#    =&amp;gt; 오르막길(0)을 우선적으로 선택해야 하므로
#       오름차순 정렬 (C=0이 앞으로 오도록 정렬)
# -------------------------------
parent = [i for i in range(N + 1)]
worst_ans = 0

# 이미 routes를 내림차순 정렬했으므로
# 뒤에서부터 접근하면 오름차순 효과
for i in range(M, -1, -1):
    A, B, C = routes[i]
    if union(A, B):
        if C == 0:
            worst_ans += 1


# -------------------------------
# 최종 결과 출력
# 피로도 = (오르막길 개수)^2 이므로,
# 최악과 최선의 피로도 차이 출력
# -------------------------------
ans = (worst_ans + best_ans) * (worst_ans - best_ans)
print(ans)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소 신장 트리(MST)가 익숙해진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크루스칼 알고리즘으로 구현하였다.&lt;/p&gt;</description>
      <category>코테/BOJ</category>
      <author>동 캄</author>
      <guid isPermaLink="true">https://dongkam.tistory.com/537</guid>
      <comments>https://dongkam.tistory.com/537#entry537comment</comments>
      <pubDate>Sat, 23 Aug 2025 22:11:07 +0900</pubDate>
    </item>
  </channel>
</rss>