[이것이 코딩테스트다] 정확한 순위

Turtle·2024년 9월 24일
0
post-thumbnail

🗃️문제 설명

선생님은 시험을 본 학생 N명의 성적을 분실하고, 성적을 비교한 결과의 일부만 가지고 있습니다.

학생 N명의 성적은 모두 다른데, 다음은 6명의 학생에 대하여 6번만 성적을 비교한 결과입니다.

  • 1번 학생의 성적 < 5번 학생의 성적
  • 3번 학생의 성적 < 4번 학생의 성적
  • 4번 학생의 성적 < 2번 학생의 성적
  • 4번 학생의 성적 < 6번 학생의 성적
  • 5번 학생의 성적 < 2번 학생의 성적
  • 5번 학생의 성적 < 4번 학생의 성적

A번 학생의 성적이 B번 학생보다 낮다면 화살표가 A에서 B를 가리키도록 할 때 위의 성적 결과를 다음 그림처럼 표현할 수 있습니다.

이 그림으로 유추해서 순위를 정확히 알 수 있는 학생도 있고, 알 수 없는 학생도 있습니다.

예를 들어 1번 학생은 5번 학생보다 성적이 낮고, 5번 학생은 4번 학생보다 성적이 낮으므로 1번 학생은 4번 학생보다 성적이 낮습니다.

따라서 1번, 3번, 5번 학생은 모두 4번 학생보다 성적이 낮다고 볼 수 있습니다.

그리고 4번 학생은 2번 학생과 6번 학생보다 성적이 낮습니다.

정리하면 4번 학생보다 성적이 낮은 학생은 3명이고, 성적이 높은 학생은 2명이므로 4번 학생의 성적 순위를 정확히 알 수 있습니다.

하지만 예시에서 4번 학생을 제외한 다른 학생은 정확한 순위를 알 수 없습니다.

학생들의 성적을 비교한 결과가 주어질 때, 성적 순위를 정확히 알 수 있는 학생은 모두 몇 명인지 계산하는 프로그램을 작성하세요.

첫째 줄에 학생들의 수 N(2 <= n <= 500)과 두 학생의 성적을 비교한 횟수 M(2 <= M <= 10,000)이 주어집니다.
다음 M개의 각 줄에는 두 학생의 성적을 비교한 결과를 나타내는 두 양의 정수 A와 B가 주어집니다.
이는 A번 학생의 성적이 B번 학생보다 낮다는 것을 의미합니다.

첫째 줄에 성적 순위를 정확히 알 수 있는 학생이 몇 명인지 출력합니다.

🖥️코드

import sys
input = sys.stdin.readline

N, M = map(int, input().split())
inf = float('inf')
maps = [[inf] * (N+1) for _ in range(N+1)]

for i in range(1, N+1):
    maps[i][i] = 0

for _ in range(M):
    a, b = map(int, input().split())
    maps[a][b] = 1  # a가 b보다 낮다.

for k in range(1, N+1):
    for a in range(1, N+1):
        for b in range(1, N+1):
            if a == b:
                continue
            maps[a][b] = min(maps[a][b], maps[a][k] + maps[k][b])

answer = 0
for i in range(1, N+1):
    cnt = 0
    for j in range(1, N+1):
        if maps[i][j] != inf or maps[j][i] != inf:
            cnt += 1
    if cnt == N:
        answer += 1
print(answer)

🧠아이디어

알고리즘 유형 : 다이나믹 프로그래밍

플로이드-워셜로 모든 경우에 대한 성적 비교 결과를 저장하고 저장된 테이블에 대해서 각 번호별로 성적 순위를 확실하게 알 수 있는 경우를 카운팅한다.

🔒문제 출처 및 참고 코드

이것이 코딩테스트다 with 파이썬 - 정확한 순위
모범 답안 - 정확한 순위

0개의 댓글