본문 바로가기
알고리즘

Python - 다리 만들기 (2146) BFS

by jun.s.gi 2023. 8. 12.
728x90

https://www.acmicpc.net/problem/2146

 

2146번: 다리 만들기

여러 섬으로 이루어진 나라가 있다. 이 나라의 대통령은 섬을 잇는 다리를 만들겠다는 공약으로 인기몰이를 해 당선될 수 있었다. 하지만 막상 대통령에 취임하자, 다리를 놓는다는 것이 아깝다

www.acmicpc.net

 - 큐에 넣는 경우의 수

    1) 다리가 만들어지지 않았다면 큐에 저장

 

1. 섬이 모두 1로 입력을 받으니 따로 섬을 구분하고 섬의 위치를 큐에 저장합니다.

2. 각 섬에서 모든 방향으로 다리를 놓습니다.

3. 다른 섬에서부터 만든 다리를 만난다면 정답을 저장합니다. (최솟값으로)

 

갔던 곳은 다시 되돌아가지 않으므로 시간복잡도는 O(n2)

import sys
from collections import deque
input = sys.stdin.readline
a = []
que = deque()
que2 = deque()
dire = [[-1, 1, 0, 0], [0, 0, -1, 1]]
freq = [[0 for i in range(100)] for j in range(100)]

def BFS(x, y, key):
    global n
    que.clear()
    que.append((x, y))
    que2.append((x, y))
    freq[x][y] = 1
    a[x][y] = key

    while que:
        ax, ay = que.popleft()

        for i in range(4):
            tx, ty = dire[0][i] + ax, dire[1][i] + ay
            if not (0 <= tx < n and 0 <= ty < n): continue
            if freq[tx][ty] or not a[tx][ty] : continue
            freq[tx][ty] = 1
            a[tx][ty] = key
            que.append((tx, ty))
            
            # 섬의 위치를 모두 두 번째 큐에 저장 해놓습니다.
            que2.append((tx, ty))


n = int(input().strip())
for i in range(n):
    a.append(list(map(int, input().strip().split())))

# 섬의 이름을 정합니다.
key = 2
for i in range(n):
    for j in range(n):
        if a[i][j] and not freq[i][j]:
            BFS(i, j, key)
            key += 1

ans = 0x7fffffff
while que2:
    x, y = que2.popleft()
    for i in range(4):
        tx, ty = x + dire[0][i], y + dire[1][i]
        if not (0 <= tx < n and 0 <= ty < n): continue
        
        # tx, ty 좌표에 바다가 아니고 다른 섬의 다리와 만났을 때 답 갱신
        if freq[x][y] * freq[tx][ty] and a[x][y] != a[tx][ty] :
            ans = min(ans, freq[x][y] + freq[tx][ty] - 2)
        if freq[tx][ty]: continue

        freq[tx][ty] += freq[x][y] + 1
        a[tx][ty] = a[x][y] # 다리놓기
        que2.append((tx, ty))
print(ans)
728x90