ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 2252 줄 세우기
    ALGORITHM/BOJ 2021. 1. 12. 22:13

    www.acmicpc.net/problem/2252

     

    2252번: 줄 세우기

    첫째 줄에 N(1≤N≤32,000), M(1≤M≤100,000)이 주어진다. M은 키를 비교한 회수이다. 다음 M개의 줄에는 키를 비교한 두 학생의 번호 A, B가 주어진다. 이는 학생 A가 학생 B의 앞에 서야 한다는 의미이

    www.acmicpc.net

    2021-01-12


    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
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Queue;
    import java.util.StringTokenizer;
     
    public class Main2252 {
        public static int N, M, arr[];
        public static List<List<Integer>> list;
        public static Queue<Integer> q;
        
        public static void main(String[] args) throws Exception{
            BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
            StringTokenizer st = new StringTokenizer(bf.readLine());
            N = Integer.parseInt(st.nextToken());
            M = Integer.parseInt(st.nextToken());
            
            arr = new int[N+1];
            list = new ArrayList<>();
            q = new LinkedList<>();
            
            for(int i = 1; i <= N+1; i++) list.add(new ArrayList<>());
        
            for(int i = 0; i < M; i++) {
                st = new StringTokenizer(bf.readLine());
                int x = Integer.parseInt(st.nextToken());
                int y = Integer.parseInt(st.nextToken());
                list.get(x).add(y); // x -> y
                arr[y]++// count 진입 차수
            }
            
            for(int i = 1; i <= N; i++) { // 진입 차수가 0이면 queue에 넣는다 
                if(arr[i] == 0) { // 진입 차수가 0이라는 의미이다.
                    q.add(i);
                }
            }
            
            StringBuilder sb = new StringBuilder();
            
            for(int i = 1; i <= N; i++) { // 학생 수를 다 돌아본다.
                if(q.isEmpty()) { // 사이클이 발생하는 경우
                    break;
                }
                
                int zero = q.poll();
                sb.append(zero + " "); // 큐에서 제거 후 순서에 저장 
                
                for(int k = 0; k < list.get(zero).size(); k++) {   
                    int num = list.get(zero).get(k); // 연결된 정점들 중에서
                    if(--arr[num] == 0) { // 간선을 제거하고 진입차수가 0이된 정점을 
                        q.add(num); // 큐에 넣어준다.
                    }
                }
            }
            
            System.out.println(sb.toString());
        }
    }
     
    cs

    #문제풀이

    위상정렬(Topological Sort)를 이용하여 푼 문제이다. 

     

    1. 선수 조건이 주어진 입력을 받을 때, 각각의 학생에 대해서 진입 차수가 있는지에 대해서도 같이 체크한다. 

     

    2. 맨 처음 모든 정점을 돌면서 진입 차수가 0인 것들은 queue에 넣는다.

     

    3. 정점의 개수만큼 돌면서, queue에서 하나씩 제거하면서 순서에 저장을 한다.

     

    4. 제거한 그 정점과 연결된 간선들을 찾아 제거 하면서, 동시에 새롭게 진입 차수가 0이 된 정점들을 체크해서 queue에 넣는다.

     

    5. 3~4를 반복한다.

     

    'ALGORITHM > BOJ' 카테고리의 다른 글

    [백준] 2096 내려가기  (0) 2021.01.19
    [백준] 2805 나무자르기  (0) 2021.01.14
    [백준] 1654 랜선 자르기  (0) 2021.01.12
    [백준] 10844 쉬운 계단 수  (0) 2021.01.09
    [백준] 14728 벼락치기  (0) 2021.01.07

    댓글

Programming Diary