코드굽는 타자기

Baekjoon[2252] - 줄 세우기 본문

알고리즘/정렬

Baekjoon[2252] - 줄 세우기

bright-jun 2020. 3. 24. 20:24

링크

 

2252번: 줄 세우기

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

www.acmicpc.net

문제설명

  • 주어진 조건대로 정렬

문제풀이

  • 위상정렬

문제코드

package baekjoon;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.StringTokenizer;

public class Main2252 {

    public static int N;
    public static int M;
    public static ArrayList<Integer>[] adj;
    public static int[] cnt;

    public static LinkedList<Integer> q;

    public static void main(String[] args) throws IOException {
        System.setIn(new FileInputStream("res/baekjoon/2252.txt"));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        StringBuilder sb = new StringBuilder();
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());

        cnt = new int[N];

        adj = new ArrayList[N];
        for (int i = 0; i < N; i++) {
            adj[i] = new ArrayList<Integer>();
        }

        int from, to;
        for (int i = 0; i < M; i++) {
            st = new StringTokenizer(br.readLine());
            from = Integer.parseInt(st.nextToken())-1;
            to = Integer.parseInt(st.nextToken())-1;
            adj[from].add(to);
//            선수과목
            cnt[to]++;
        }

//        위상정렬
        q = new LinkedList<Integer>();

//        adj cnt 0인 애들 q에 집어넣기
        for (int i = 0; i < N; i++) {
            if(cnt[i]==0) {
                q.add(i);
            }
        }

        int now;
        int ls;
        int c;
        while(!q.isEmpty()) {
            now = q.poll();
            sb.append(now+1).append(" ");
            ls = adj[now].size();
            for (int i = 0; i < ls; i++) {
                c=--cnt[adj[now].get(i)];
                if(c==0) {
                    q.add(adj[now].get(i));
                }
            }
        }
        System.out.print(sb);
    }
}

아쉬운점

  • 상황에 맞는 최적화된 자료구조를 잘 사용하지 못하였음
    • 인접리스트를 구현할 때는 데이터의 삭제,추가가 상대적으로 적음
      • ArrayList써야함
      • LinkedList쓰면 시간초과 남

잘한점

  • 위상정렬을 구현하였다.

    • 추후 포스팅
  • O(N)

    • N<32000이라 인접행렬을 구하면 32000^2라 메모리 초과임
  • 최적화

    • Stringbuilder사용

    • List.get(i)[idx]접근하는데에 시간이 오래 걸림

    • for (int i = 0; i < ls; i++) {
             cnt[adj[now].get(i)]--;
             if(cnt[adj[now].get(i)]==0) {
                 q.add(adj[now].get(i));
             }
         }

      를 바꿈

    • for (int i = 0; i < ls; i++) {
             c=--cnt[adj[now].get(i)];
             if(c==0) {
                 q.add(adj[now].get(i));
             }
         }

 

'알고리즘 > 정렬' 카테고리의 다른 글

Baekjoon[2623] - 음악프로그램  (0) 2020.03.24
SWEA[7701] - 염라대왕의 이름 정렬[D4]  (0) 2020.03.12
Comments