본문 바로가기

문제 노트/정올

등수 찾기( BOJ 17616 )

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

 

17616번: 등수 찾기

표준 입력으로 다음 정보가 주어진다. 첫 번째 줄에 세 정수 N, M, X가 공백을 사이에 두고 주어진다. (2 ≤ N ≤ 105, 1 ≤ M ≤ min(N(N-1)/2, 5×105), 1 ≤ X ≤ N) . 다음 M 줄에는 각각 두 정수 A, B가 주어

www.acmicpc.net

 

문제 파악하기

N명의 사람 중 주어진 X가 될 수 있는 등수의 범위를 찾는 문제입니다. 등수의 범위라고 하니 뭔가 확률적으로 생각해야 될 것처럼 보이지만 등수의 의미를 생각한다면 그리 어렵지 않게 풀 수 있는 문제입니다.

 

문제 해결하기

그렇다면 등수의 의미는 무엇일까요? 등수란 자신보다 앞에 몇 명이 있으며, 뒤에 몇 명이 있는지를 나타내는 수치입니다. 만약 내 앞에 5명 중 1명의 사람이 있다면 나는 현재 2등이라는 의미이며, 반대로 5명 중 내 뒤에 1명의 사람만 있다면 나는 현재 4등이라는 의미입니다. 그렇기에 우리는 X의 앞에 몇 명이 있으며, 뒤에 몇 명이 있는지에 따라 등수의 범위를 구할 수 있습니다.

 

앞/뒤에 몇 명이 있는지는 주어진 정보를 그래프로 변환하여 탐색하면 구할 수 있습니다. 간선의 비용을 각각 다르게 설정한 다음, DFS/BFS를 활용하면 앞/뒤에 각각 몇 명의 사람이 있는지 구할 수 있습니다. 그리고 우리는 구한 값을 토대로 X가 가질 수 있는 순위의 최솟값과 최댓값을 구할 수 있습니다. 기본적인 소스코드는 다음과 같습니다.

 

소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>
#include <string.h>
#include <vector>
#include <utility>
#define NMAX 100010
#define PAIR pair<intint>
using namespace std;
 
int N, M, X;
int A, B;
 
int visited[NMAX];
vector< int > ans;
vector< PAIR > graph[NMAX];
 
int search(int cur, int d) {
    int nxt, nd, cnt=0;
 
    for(PAIR p:graph[cur]) {
        nxt = p.first;
        nd = p.second;
        if(d != nd or visited[nxt]) continue;
 
        visited[nxt] = 1;
        cnt += search(nxt, d)+1;
    }
 
    return cnt;
}
 
int main() {
    scanf("%d %d %d"&N, &M, &X);
    for(int i=1;i<=M;i++) {
        scanf("%d %d"&A, &B);
 
        graph[A].push_back({B, 1});
        graph[B].push_back({A, -1});
    }
 
    // d=-1: X보다 큰 값 개수 / d=1: X보다 작은 값 개수
    for(int d=-1;d<=1;d+=2) {
        memset(visited, 0sizeof(visited));
 
        visited[X] = 1;
        ans.push_back(search(X, d));
    }
 
    printf("%d %d", ans[0]+1, N-ans[1]);
 
}
cs

후기

순위를 가장한 그래프 문제입니다. 주어진 정보를 그래프로 바꿔서 생각할 수 있는지 물어보는 문제로, 정올 문제답게 생각이 필요한 문제라고 생각합니다. 그래프를 연습하는 사람에게 추천하고 싶은 좋은 문제입니다.

'문제 노트 > 정올' 카테고리의 다른 글

헬기 착륙장( BOJ 22348 )  (0) 2022.03.22
등산 마니아( BOJ 20188 )  (0) 2022.03.22
자동차경주( BOJ 2611 )  (0) 2022.03.06
다이어트( BOJ 19942 )  (0) 2022.02.19
햄버거 분배( BOJ 19941 )  (0) 2022.02.18