백준_물대기

임정민·2024년 1월 12일
1

알고리즘 문제풀이

목록 보기
143/173
post-thumbnail

백준 골드2 문제입니다. 실전에 대비하기 위해 60분 시간제한을 두고 풀었습니다.

문제

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

[나의 풀이]

⌛ 시간초과 (5% KeyValue Error)


def find(x):

    x = int(x)
    if parent[x]!=x:
        parent[x] = find(parent[x])

    return parent[x]

def union(a,b):

    a = find(a)
    b = find(b)

    if a<b:
        parent[b] = a
    else:
        parent[a] = b

N = int(input())
connects = {} # {'00':5}
parent = {i:i for i in range(N)} # {0:0}
ans = 0

for i in range(N):
    connects[str(i)+str(i)] = int(input()) # {'00':2}
ans += min(connects.values())

for i in range(N):
    connect = map(int,input().split())
    for j,con in enumerate(connect):
        if con>0:
            connects[str(i)+str(j)] = con # {'01':2}

print(parent)
print(connects)

for connect in sorted(connects.items(),key= lambda x : x[1]):
    print("---------------")
    # print(connect)
    # ('01', 2)
    a,b = connect[0]
    print(a,b)
    # if connect[1]>0:
    if find(a) != find(b):
        union(a,b)
        print(a,b,"연결")
        print(connects[connect[0]],"추가")
        ans += connects[connect[0]]

print(ans)

N개의 논이 주어지고 각 논별로 비용이 다른 우물을 설치할 수 있으며 다른 논의 우물을 연결하여 물을 댈 수 있을 때, 모든 논에 물을 연결하는 최솟값을 구하는 문제입니다.🐓🐓🐓

가장 먼저 Union-Find를 활용한 크루스칼 알고리즘을 생각히여 해결하려고 했습니다.

하나의 우물을 가지고 있는 논을 모두 연결하는 방식으로 구현하려고 하였습니다.

connects라는 dict() 객체로 0번째 논에 우물을 직접 설치할 때는 '00':1과 같이 표현한 뒤,전체 논들 중 가장 저렴하게 우물을 직접 설치하고

ans += min(connects.values())

0번째 논에서 1번째 논으로 물을 연결할 때는 '01':2와 같이 표현하였는데 대부분 케이스에서 KeyError가 발생하여 시간이 지체되었고 해결하기 어려웠습니다.

이후 다른 사람의 풓이를 참고하여 이해하였습니다.

[다른 사람의 풀이1]


def find(x):

    if parent[x]!=x:
        parent[x] = find(parent[x])

    return parent[x]

def union(a,b):

    a = find(a)
    b = find(b)

    if a<b:
        parent[b] = a
    else:
        parent[a] = b

N = int(input())
connects = []
parent = [i for i in range(N+1)]
ans = 0

for i in range(1,N+1):
    well = int(input())
    connects.append((well,0,i))

for i in range(1,N+1):
    connect = list(map(int,input().split()))
    for j in range(i+1,N+1):
        connects.append((connect[j-1],i,j))

print(parent)
print(connects)

# cnt = 0
for connect in sorted(connects):
    print("---------------")
    # print(connect)
    cost,a,b = connect
    print(cost,a,b)
    # if connect[1]>0:
    # if cnt==N:
    #     break
    if find(a) != find(b):
        union(a,b)

        ans += cost
        # cnt += 1

print(ans)

'나의 풀이'와 같이 크루스칼 알고리즘을 활용하되 논에 직접 우물을 설치하는 것을 (비용,0,설치할 논 인덱스)로 표현한 것이 포인트였습니다.🐋🐋🐋


for i in range(1,N+1):
    well = int(input())
    connects.append((well,0,i))

우물을 논과 같이 아예 0번 인덱스로 정의하고 논을 N+1개까지 규정하여 우물이 연결되게끔 모든 논들을 연결하면 되는 것 이였습니다.

[다른 사람의 풀이2]


	import sys
 
input = sys.stdin.readline
 
N = int(input())
edge = []
cost = []
def find_parent(ind):
    if make_set[ind] == ind:
        return ind
    make_set[ind] = find_parent(make_set[ind])
    return make_set[ind]
 
 
def union(A,B):
    X = find_parent(A)
    Y = find_parent(B)
 
    if X != Y:
        if rank[X] < rank[Y]:
            X,Y = Y,X
        make_set[Y] = X
        if rank[X] == rank[Y]:
            rank[X] += 1
 
for i in range(N):
    pay = int(input())
    edge.append((pay,0,i+1))
    cost.append(pay)
 
arr = [list(map(int,input().split())) for _ in range(N)]
for i in range(N):
    for j in range(i):
        edge.append((arr[i][j],i+1,j+1))
 
 
 
make_set = [i for i in range(N+1)]
rank = [0 for _ in range(N+1)]
edge.sort()
cnt = 0
result = 0
for pay,a,b in edge:
    if find_parent(a) != find_parent(b):
        cnt += 1
        result += pay
        union(a,b)
    if cnt == N:
        break
print(result)

'다른 사람의 풀이1'과 같은 방식의 풀이이되, 최솟값을 찾을 때 모든 논이 연결되어 있을 때 바로 종료하는 부분만 달랐습니다.


if cnt == N:
	break

감사합니다.🐣🐣🐣

profile
https://github.com/min731

0개의 댓글