Algorithm

[BOJ] 3665. 최종 순위

프로그래민 2021. 6. 24. 22:58
반응형

위상정렬을 이용하여 풀었던 그래프문제이다.

이 문제를 맨처음 접했을 때 각 노드끼리의 순위가 존재하고 싸이클이 없기에 위상정렬을 사용해보았다. 맨처음 문제를 접근을 다음과 같이해보았다. 만일 1등, 2등, 3등, 4등이 존재한다면 4등->3등, 3등->2등, 2등->1등 이런식으로 그래프를 그려보았다. 하지만 이 문제는 순위가 뒤바뀌는 경우가 있는데 맨처음 내가 적용한 방식은 순위가 뒤바뀌는 것을 처리해주지 못하기에 그래프를 새롭게 그려보았다. 즉, 4등->3등, 4등->2등, 4등->1등, 3등->2등, 3등->2등, 2등->1등과 같이 순위가 낮은것이 자기보다 높은 순위를 모두 볼수 있도록 그래프를 그리는 방식을 수정하였다. 이런 방식을 통해 순위가 바뀌는 경우도 처리해주었고, 그래프를 새로그린다음에 위상정렬을 하였다.

이 문제에서는 순위가 애매해지는 "?"와 모순이 생기게 되는 "IMPOSSIBLE"을 처리해주는 부분이 있다. 순위가 애매해지는 경우는 위상정렬을 돌면서 동순위가 생기게 되는 경우인데 그 경우는 queue에서 하나를 뽑았을 때 queue에 남아있다면 애매해지는 방식으로 처리했다. 모순이 생기게 되는 경우는 위상정렬을 노드의 갯수만큼 못도는 경우 애매하게 처리하였다.

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package algostudy2;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main_bj_3665_최종순위 {
    static int N;
    static int[] indegree;
    static int[][] map;
    static int[] oldRank;
    static int[] newRank;
 
    static Queue<Integer> queue;
 
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = null;
        StringBuilder sb = new StringBuilder();
 
        int T = Integer.parseInt(br.readLine());
 
        for (int tc = 1; tc <= T; tc++) {
            N = Integer.parseInt(br.readLine());
 
            oldRank = new int[N + 1];
 
            st = new StringTokenizer(br.readLine());
            for (int i = 1; i <= N; i++) {
                oldRank[i] = Integer.parseInt(st.nextToken());
            }
 
            initData();
 
            int change = Integer.parseInt(br.readLine());
            for (int i = 0; i < change; i++) {
                st = new StringTokenizer(br.readLine());
 
                int num1 = Integer.parseInt(st.nextToken());
                int num2 = Integer.parseInt(st.nextToken());
 
                //순위를 바꾸는 작업
                if (map[num1][num2] == 1) {
                    map[num1][num2] = 0;
                    indegree[num2]--;
                    map[num2][num1] = 1;
                    indegree[num1]++;
                } else {
                    map[num2][num1] = 0;
                    indegree[num1]--;
                    map[num1][num2] = 1;
                    indegree[num2]++;
                }
            }
 
            int curRank = topological();
 
            if (curRank == 0) {            //정상적인 경우
                for (int i = 1; i <= N; i++) {
                    sb.append(newRank[i] + " ");
                }
                sb.append("\n");
            } else if (curRank == -1) {        //순위가 애매한 경우
                sb.append("?\n");
            } else {                    //모순이 생기는 경우
                sb.append("IMPOSSIBLE\n");
            }
        }
        System.out.print(sb.toString());
    }
 
    static void initData() {
        indegree = new int[N + 1];
        map = new int[N + 1][N + 1];
 
        for (int index1 = 1; index1 <= N - 1; index1++) {
            for (int index2 = index1 + 1; index2 <= N; index2++) {
                int end = oldRank[index1];
                int start = oldRank[index2];
 
                map[start][end] = 1;
                indegree[end]++;
            }
        }
    }
 
    static int topological() {
        int curRankIndex = N;
        newRank = new int[N + 1];
 
        queue = new LinkedList<>();
 
        for (int i = 1; i <= N; i++) {
            if (indegree[i] == 0) {
                queue.offer(i);
            }
        }
 
        while (!queue.isEmpty()) {
            int cur = queue.poll();
 
            //하나를 뻇는데도 queue에 남아있다면 애매한 경우
            if (queue.size() > 0) {
                return -1;
            }
 
            newRank[curRankIndex] = cur;
            curRankIndex--;
 
            for (int i = 1; i <= N; i++) {
                if (map[cur][i] == 1) {
                    int next = i;
 
                    indegree[next]--;
 
                    if (indegree[next] == 0) {
                        queue.offer(next);
                    }
                }
            }
 
        }
 
        return curRankIndex;
    }
}
 
                                    
반응형

'Algorithm' 카테고리의 다른 글

[BOJ] 1005. ACM Craft  (0) 2021.06.24
[BOJ] 2637. 장난감 조립  (0) 2021.06.24
[BOJ] 2610. 회의준비  (0) 2021.06.15
[BOJ] 1238. 파티  (0) 2021.06.15
[BOJ] 11562. 백양로 브레이크  (0) 2021.06.15