ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Q. 3584 자바 : 가장 가까운 공통 조상
    코딩테스트/백준_Java 2023. 4. 16. 09:53

    Q. 3584 자바 : 가장 가까운 공통 조상

     

    문제 : boj.kr/3584

    골드 4 난이도의 문제이다.

     

    트리의 정점의 수와 간선이 주어진다.

    이후 두 정점이 주어지면 공통조상 정점을 출력하는 문제이다.

    주의해야 할 점은 루트 노드는 1번 정점이 아니라는 점 이다.

     

    아래와 같은 풀이로 풀었다.

    1. Tree class를 만든다. 트리 클래스는 인덱스, 깊이, 자식, 부모의 정보를 가진다.

    (루트 노드가 1번 정점이 아니므로  1번 정점의 부모가 null일 때 까지 정점을 이동시키고 dfs를 통해 깊이를 저장했다.)

    2. 두 정점이 주어졌을 때 공통 조상을 찾기 위해 깊이를 동일하게 맞춘다.

    3. 이후 한 칸씩 부모로 올라가며 공통 조상이 나올 때 까지 반복한다.

    (풀고나서 다른 풀이를 찾아보니 좀 비효율적으로 푼 것 같다..)

    그리고 공통 조상 탐색 알고리즘인 lca 알고리즘이 있지만,

    기억이 잘 안났고 시간복잡도도 문제 없을 것 같아 적은 방식대로 풀었다.

     

    시간 복잡도는 N의 크기가 최대 10,000이고

    만약 두 정점이 양 쪽 끝에 있는 경우(두 정점이 ㅅ 모양의 양 끝 정점인 경우)

    공통 조상은 루트 노드가 되고 최악의 시간복잡도를 가진다.

     

    시간복잡도를 계산하면

    깊이를 계산하기 위한 dfs - O(log N)

    공통 조상 계산 - O(2 * N log N)이 된다.

    따라서 시간복잡도는 약 O(N log N)이므로 시간초과는 걱정하지 않아도 된다.

     

    아래와 같이 풀었다.

    import java.io.*;
    import java.util.*;
    
    public class Main {
        static FastReader scan = new FastReader();
        static StringBuilder sb = new StringBuilder();
    
        static int n, v1, v2;
        static Tree[] trees;
    
        static class Tree{
            int depth = 0, idx = 0;
            List<Tree> child;
            Tree parent;
            Tree() {
                child = new ArrayList<>();
            }
        }
        static void input() {
    
            n = scan.nextInt();
            trees = new Tree[n + 1];
            for (int i = 1; i <= n; i++) {
                trees[i] = new Tree();
                trees[i].idx = i;
            }
            for (int i = 1; i < n; i++) {
                int v1 = scan.nextInt();
                int v2 = scan.nextInt();
                trees[v1].child.add(trees[v2]);
                trees[v2].parent = trees[v1];
            }
    
            v1 = scan.nextInt();
            v2 = scan.nextInt();
        }
    
        static void lca() {
    
            Tree v1Tree = trees[v1];
            Tree v2Tree = trees[v2];
            if (v1Tree.depth > v2Tree.depth) {
                while (v1Tree.depth != v2Tree.depth) {
                    v1Tree = v1Tree.parent;
                }
            }else if (v1Tree.depth < v2Tree.depth) {
                while (v1Tree.depth != v2Tree.depth) {
                    v2Tree = v2Tree.parent;
                }
            }
            while (v1Tree != v2Tree) {
                v1Tree = v1Tree.parent;
                v2Tree = v2Tree.parent;
            }
            System.out.println(v1Tree.idx);
        }
    
        static void calDepth(Tree tree, int depth) {
    
            tree.depth = depth;
            for (Tree t: tree.child) {
                calDepth(t, depth + 1);
            }
        }
    
        static void pro() {
    
            Tree tree = trees[1];
            while (tree.parent != null) tree = tree.parent;
            calDepth(tree, 0);
            lcs();
        }
    
        public static void main(String[] args) {
    
            for (int i = scan.nextInt(); i > 0; i--) {
                input();
                pro();
            }
        }
    
    
        static class FastReader {
            BufferedReader br;
            StringTokenizer st;
    
            public FastReader() {
                br = new BufferedReader(new InputStreamReader(System.in));
            }
    
            public FastReader(String s) throws FileNotFoundException {
                br = new BufferedReader(new FileReader(new File(s)));
            }
    
            String next() {
                while (st == null || !st.hasMoreElements()) {
                    try {
                        st = new StringTokenizer(br.readLine());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                return st.nextToken();
            }
    
            int nextInt() {
                return Integer.parseInt(next());
            }
    
            long nextLong() {
                return Long.parseLong(next());
            }
    
            double nextDouble() {
                return Double.parseDouble(next());
            }
    
            String nextLine() {
                String str = "";
                try {
                    str = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return str;
            }
        }
    }
    반응형

    '코딩테스트 > 백준_Java' 카테고리의 다른 글

    Q. 12427 자바 : 회사 문화 1  (0) 2023.04.19
    Q. 15681 자바 : 트리와 쿼리  (0) 2023.04.17
    Q. 20364 자바 : 부동산 다툼  (0) 2023.04.15
    Q. 15900 자바 : 나무 탈출  (0) 2023.04.14
    Q. 5567 자바 : 결혼식  (0) 2023.04.12

    댓글

Designed by Tistory.