본문 바로가기

알고리즘 삽질장

[인프런] 회장뽑기

반응형


문제설명

월드컵 축구의 응원을 위한 모임에서 회장을 선출하려고 한다. 이 모임은 만들어진지 얼마 되지 않았기 때문에 회원 사이에 서로 모르는 사람도 있지만, 몇 사람을 통하면 서로 모두 알 수 있다. 각 회원은 다른 회원들과 가까운 정도에 따라 점수를 받게 된다. 예를 들어, 어느 회원이 다른 모든 회원과 친구이면 이 회원의 점수는 1점이다. 어느 회원의 점수가 2점이면, 다른 모든 회원이 친구이거나 친구의 친구임을 뜻한다. 또, 어느 회원의 점수가 3점이면, 다른 모든 회원이 친구이거나, 친구의 친구이거나, 친구의 친구의 친구임을 말한다. 4점, 5점도 같은 방법으로 정해진다.

각 회원의 점수를 정할 때 주의할 점은 어떤 두 회원이 친구 사이이면서 동시에 친구의 친구사이이면, 이 두사람은 친구사이라고 본다. 회장은 회원들 중에서 점수가 가장 작은 사람이 된다. 회장의 점수와 회장이 될 수 있는 모든 사람을 찾는 프로그램을 작성해라.

입력조건

  • 첫줄에는 회원의 수가 주어진다. 단, 회원의 수는 50명을 넘지 않는다.
  • 둘째 줄부터 한 줄에 두 개의 회원번호가 있는데, 이것은 두 회원이 서로 친구임을 의미한다. 회원번호는 1부터 회원의 수만큼 번호가 붙어있다. 마지막 줄에는 -1이 두개 들어있다. 이것이 입력 종료 조건이다.

출력조건

  • 첫줄은 회장 후보의 점수와 회장 후보 수를 출력하고 두 번째 줄은 회장 후보를 모두 출력한다.

사고과정

  • 처음에 친구의 친구가 무슨 이야기인가... 싶었는데, 알고보니 이게 그래프에서 간선 비용을 의미하는 것이었다. 그것이 점수로 치환되어 나타난 것!
  • 모든 회원의 점수를 최솟값을 구하면 된다. 플로이드 워셜 알고리즘을 활용해 최단 거리를 구하는 셈! 최단거리를 구하는 힌트로는 문제에서 "각 회원의 점수를 정할 때 주의할 점은 어떤 두 회원이 친구 사이이면서 동시에 친구의 친구사이이면, 이 두사람은 친구사이라고 본다."라는 텍스트에서 캐치할 수 있었다.

풀이

n = int(input())
INF = int(1e8)
graph = [[INF] * (n+1) for _ in range(n+1)]
while True:
    a, b = map(int, input().split())
    if a == -1 and b == -1:
        break
    graph[a][b] = 1
    graph[b][a] = 1

for a in range(1, n+1):
    graph[a][a] = 0

for k in range(1, n+1):
    for a in range(1, n+1):
        for b in range(1, n+1):
            graph[a][b] = min(graph[a][b], graph[a][k]+graph[k][b])

min_val = INF
for i in range(1, n+1):
    min_val = min(min_val, max(graph[i][1:]))
result = []
for i in range(1, n+1):
    if max(graph[i][1:]) == min_val:
        result.append(str(i))
print(min_val, len(result))
print(' '.join(result))
반응형