본문 바로가기
알고리즘

Algorithm - 회장뽑기(플로이드-와샬 응용)

by DGK 2022. 2. 12.

 

알고리즘 입문 수업을 듣고 중요한 내용을 정리했습니다.
개인 공부 후 자료를 남기기 위한 목적이므로 내용 상에 오류가 있을 수 있습니다.

 

문제

[회장뽑기(플로이드-와샬 응용)]

 

월드컵축구의 응원을 위한 모임에서 회장을 선출하려고 한다.

이 모임은 만들어진지 얼마 되지 않았기 때문에 회원사이에 서로 모르는 사람도 있지만, 몇 사람을 통하면 서로 모두 알 수 있다. 각 회원은 다른 회원들과 가까운 정도에 따라 점수를 받게된다.

 

예를 들어, 어느 회원이 다른 모든 회원과 친구이면, 이 회원의 점수는 1점이다. 어느 회원의 점수가 2점이면, 다른 모든 회원이 친구이거나, 친구의 친구임을 말한다. 또한, 어느 회원의 점수가 3점이면, 다른 모든 회원이 친구이거나, 친구의 친구이거나, 친구의 친구의 친구임을 말한다. 4점, 5점등은 같은 동일한 방법으로 정해진다.

 

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

 

 

*입력 설명

첫 번째 줄에는 회원의 수가 주어진다.

단, 회원의 수는 50명을 넘지 않는다.

두 번째 줄부터는 한 줄에 두 개의 회원번호가 있는데, 이것은 두 회원이 서로 친구임을 나타낸다.

참고로 회원번호는 1부터 회원의 수만큼 번호가 붙어있다.

마지막 줄에는 두 개의 -1이 주어진다.

 

*출력 설명

첫 번째 줄에는 회장 후보의 점수와 회장후보 수를 출력한다.

두 번째 줄에는 회장 후보를 모두 출력한다.

 

 


 

 

풀이(Python)

답안

import sys
sys.stdin = open('AA/input_84.txt', 'rt')

if __name__ == "__main__":
    n = int(input())
    dis = [[100] * (n+1) for _ in range(n+1)]
    res = [0] * (n+1)
    for i in range(1, n+1):
        dis[i][i] = 0
        
    while True:
        a, b = map(int, input().split())
        if a == -1 and b == -1:
            break
        dis[a][b] = 1
        dis[b][a] = 1
        
    for k in range(1, n+1):
        for i in range(1, n+1):
            for j in range(1, n+1):
                dis[i][j] = min(dis[i][j], dis[i][k]+dis[k][j])

    score = 100
    for i in range(1, n+1):
        for j in range(1, n+1):
            res[i] = max(res[i], dis[i][j])
        score = min(score, res[i])
    out = []
    for i in range(1, n+1):
        if res[i] == score:
            out.append(i)
    print(score, len(out))
    for x in out:
        print(x, end=' ')
        
'''
출력 :
2 3
2 3 4

'''

 

input_84.txt(입력)

5
1 2
2 3
3 4
4 5
2 4
5 3
-1 -1

 

 

중요내용

  1. 2차원 리스트 dis에는 각 회원들 간의 관계정보(점수)가 저장된다.
  2. 참고로, 각 회원들과의 점수들 중 최대값이 해당 회원의 점수가 된다.
  3. 주어진 입력정보를 바탕으로 노드와 간선으로 구성된 트리구조를 만들어서 생각하면 관계를 파악하는데 훨씬 수월하다.
  4. 모든 노드에서 모든 노드로 가는 최단거리를 구하는데 플로이드-와샬 개념이 사용된다.
  5. 즉, dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]) 코드가 플로이드-와샬 개념이 적용된 코드이다.
  6. 참고로, dis[0][0] = 0은 자기자신과의 가까운 정도를 의미하므로 0이 되는 것이다.
  7. 리스트 res에는 각 회원의 점수가 저장된다.
  8. 또한, 리스트 res에서의 최소값이 회장후보의 점수가 된다.
  9. 변수 score에는 회장점수가 저장된다.
  10. 리스트 out에는 회장후보들의 인덱스번호가 저장된다.

 

 

댓글