본문 바로가기
알고리즘 문제 풀이

[백준 17616] 등수 찾기

by 다빈치코딩 2024. 11. 3.

목차

    반응형

    문제 출처 : https://www.acmicpc.net/problem/17616

     

    이 문제는 2019년 정보 올림피아드 초등부 2차 3번 문제 입니다.

     

    문제 이해하기

    두 학생중 누가 더 잘했느냐를 종합하여 특정 학생 X의 등수 범위를 파악해야하는 문제 입니다.

    문제의 예제 입력3번을 보겠습니다. 

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

     

    해당 입력을 그림으로 표현하면 아래와 같습니다.

    1, 2번을 제외한 3, 4, 5번의 등수는 확실하게 알 수 있습니다. 하지만 1번이 1등인지 2번이 1등인지 알 수 없습니다. 따라서 1번의 범위는 최대 1등, 최소 2등이 됩니다.

    보통 DFS, BFS 문제를 풀 때 방향성을 고려하지 않는 양방향으로 구현하지만 이 문제에서는 단방향으로 해야 합니다. 단방향으로 자신보다 높은 성적을 가진 친구들의 그래프, 단방향으로 자신보다 낮은 성적을 가진 친구들의 그래프를 가지고 있다면 해당 번호의 등수의 범위를 쉽게 알 수 있습니다.

    가령 3번의 등수를 찾기 위해서는 3번보다 높은 등수의 친구들이 몇 명인지 찾아야 합니다. 위에서는 1, 2번으로 최소 3등이라는 것을 알 수 있습니다. 반대로 3번보다 낮은 등수의 친구들이 몇 명인지 파악합니다. 4, 5번으로 전체 5명 중 2명보다 상위이기 때문에 최대 3등이라는 것을 알 수 있습니다.

    코드 작성하기

    그럼 코드를 직접 작성해 보겠습니다.

    입력 받기

    N, M, X = map(int, input().split())
    
    win_arr = [[] for _ in range(N+1)]
    lose_arr = [[] for _ in range(N+1)]
    for _ in range(M):
        a, b = map(int, input().split())
        lose_arr[a].append(b)
        win_arr[b].append(a)
    

    전체 인원인 N명의 학생, 총 질문 수 M번, 등수를 알고 싶은 학생 X를 입력으로 받습니다. 다음으로 M번의 질문을 통해 학생들의 관계를 입력 받습니다. win_arr에는 자신보다 등수가 높은 학생들로 연결되고, lose_arr에는 자신보다 등수가 낮은 학생들로 연결 됩니다. 따라서 어떤 학생을 기준으로 win_arr에 몇 명이나 연결되어 있는지 확인하면 최대 몇 등인지 알 수 있습니다. 자신보다 잘하는 친구들 3명이 앞에 있다면 아무리 잘해도 4등이상 할 수 없습니다.

    반대로 lose_arr에 몇 명이나 연결되어 있는지 확인하면 최소 몇 등이 되는지 알 수 있습니다. 전체 인원이 10명인데 자신보다 등 수가 낮은 친구들이 2명 있다면 10 - 2로 최소 8등을 할 수 있다는 것을 알 수 있습니다.

    BFS 함수

    from collections import deque
    
    visited = [False] * (1+N)
    def bfs(x, arr):
        q = deque([x])
        cnt = 0
        while q:
            node = q.popleft()
            for nxt in arr[node]:
                if visited[nxt]:
                    continue
                visited[nxt] = True
                q.append(nxt)
                cnt += 1
                
        return cnt
    

    간단한 bfs 함수 입니다. arr에 연결되어 있는 친구들이 몇 명인지 cnt를 통해 확인할 수 있습니다. 마지막에 cnt를 리턴하여 원하는 자신보다 등수가 높은 친구들이 몇 명인지, 반대로 자신보다 등수가 낮은 친구들이 몇 명인지 확인할 수 있습니다.

    출력하기

    U = bfs(X, win_arr)
    V = bfs(X, lose_arr)
    
    print(f'{U + 1} {N - V}')
    

    U는 자신보다 등 수가 높은 친구들이 몇 명인지 알 수 있습니다. V는 자신보다 등 수가 낮은 친구들이 몇 명인지 알 수 있습니다.

    자신보다 등 수가 높은 친구가 없다면 0이 리턴됩니다. 이 경우 자신의 위치인 1을 더해 1등이 됩니다. 자신의 앞에 있는 친구의 수에다가 1을 더해 몇 등인지 파악이 가능합니다.

    V는 자신보다 낮은 등수의 친구들이 몇 명인지를 확인할 수 있습니다. 전체 인원에서 V값을 빼 최소 몇 등인지 확인할 수 있습니다.

    visited의 경우 U를 구할 때, V를 구할 때 각각 초기화를 해야되는거 아닌가 생각할 수 있습니다. 하지만 그럴 필요가 없습니다. 왜냐하면 문제에서 입력이 정확하다는 점을 보장하였기 때문입니다. 어떤 친구 X를 기준으로 자신보다 등수가 높으면서, 낮은 경우가 없습니다. 즉 한 번 방문한 친구는 더 이상 방문하는 경우가 없다는 뜻입니다. 따라서 visited를 매 번 초기화 하지 않아도 됩니다.

    전체 코드

    전체 코드를 확인해 보겠습니다.

    from collections import deque
    
    N, M, X = map(int, input().split())
    
    win_arr = [[] for _ in range(N+1)]
    lose_arr = [[] for _ in range(N+1)]
    for _ in range(M):
        a, b = map(int, input().split())
        lose_arr[a].append(b)
        win_arr[b].append(a)
    
    visited = [False] * (1+N)
    def bfs(x, arr):
        q = deque([x])
        cnt = 0
        while q:
            node = q.popleft()
            for nxt in arr[node]:
                if visited[nxt]:
                    continue
                visited[nxt] = True
                q.append(nxt)
                cnt += 1
        return cnt
    
    U = bfs(X, win_arr)
    V = bfs(X, lose_arr)
    
    print(f'{U + 1} {N - V}')
    
    반응형

    '알고리즘 문제 풀이' 카테고리의 다른 글

    [백준 11057] 오르막 수  (0) 2024.11.08
    [백준 2624] 동전 바꿔주기  (0) 2024.11.07
    [백준 20187] 종이접기  (1) 2024.10.15
    [백준 32069] 가로등  (1) 2024.10.03
    [백준 4779] 칸토어 집합  (1) 2024.10.01