문제 링크

성능 요약

메모리: 205512 KB, 시간: 456 ms

 

분류

백트래킹, 깊이 우선 탐색, 그래프 이론, 그래프 탐색

 

문제 설명

BOJ 알고리즘 캠프에는 총 N명이 참가하고 있다. 사람들은 0번부터 N-1번으로 번호가 매겨져 있고, 일부 사람들은 친구이다.

오늘은 다음과 같은 친구 관계를 가진 사람 A, B, C, D, E가 존재하는지 구해보려고 한다.

  • A는 B와 친구다.
  • B는 C와 친구다.
  • C는 D와 친구다.
  • D는 E와 친구다.

위와 같은 친구 관계가 존재하는지 안하는지 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 사람의 수 N (5 ≤ N ≤ 2000)과 친구 관계의 수 M (1 ≤ M ≤ 2000)이 주어진다.

둘째 줄부터 M개의 줄에는 정수 a와 b가 주어지며, a와 b가 친구라는 뜻이다. (0 ≤ a, b ≤ N-1, a ≠ b) 같은 친구 관계가 두 번 이상 주어

지는 경우는 없다.

 

출력

문제의 조건에 맞는 A, B, C, D, E가 존재하면 1을 없으면 0을 출력한다.

 

풀이 (DFS)

시간 복잡도 O(N) 공간 복잡도 O(N)

아이디어: 문제에서는 A-B-C-D-E의 관계가 존재하는지 묻고 있기에 이는 곧 그래프 정보에서 깊이가 5인 구간이 존재하는지 여부를 묻는 다고 볼 수 있다. 따라서 DFS(깊이 우선 탐색)을 사용하여 만약 5이상의 깊이를 가지는 구간이 존재한다면 1을 출력시키고 프로그램을 종료시키면 된다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    static HashMap<Integer, ArrayList<Integer>> map;
    static boolean[] visited;
    static int depth;
    public static boolean dfs(int node){
        depth++;
        // 깊이가 5이면 문제에서 원하는 관계가 존재하기에 true
        if(depth ==5) return true;
        // 현재 노드를 방문한 것으로 표시
        visited[node] = true;

        // 현재 노드에 인접한 모든 노드를 확인
        ArrayList<Integer> nextNodes = map.get(node);
        for (Integer nextNode : nextNodes) {
            if(!visited[nextNode])
                if(dfs(nextNode))
                    return true;
        }
        // 깊이 감소
        depth--;
        visited[node] = false; // 방문 초기화
        return false;
    }
    public static int sti(StringTokenizer st){
        return Integer.parseInt(st.nextToken());
    }
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int N = sti(st), M = sti(st);
        map = new HashMap<>();
        for (int i = 0; i < N; i++) map.put(i,new ArrayList<>());
        boolean ans = false;

        for (int i = 0; i < M; i++) {
            st = new StringTokenizer(br.readLine());
            int op1 = sti(st), op2 = sti(st);
            // 같은 관계는 두번 이상 주어지지 않는다.
            map.get(op1).add(op2);
            map.get(op2).add(op1);
        }
        // 깊이가 5면 1 아니면 0
        for (int i = 0; i < N; i++) {
            visited = new boolean[N];
            depth = 0;
            if (dfs(i)) {
                System.out.println(1);
                return;
            }
        }
        System.out.println(0);
    }
}

참고하여 개선된 풀이 (DFS)

아이디어: static HashMap<Integer, ArrayList<Integer>> map; 자료구조를 단순한 연결 리스트 형식의 자료구조로 변경함으로써 버킷배열, 해시 함수, 재해시 연산을 줄임으로서 오버헤드를 줄여 메모리와 속도를 둘다 개선

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    static int answer = 0;
    static boolean[] visited;
    static Node[] map;
    static class Node{
        int vertex;
        Node link;

        public Node(int vertex, Node link) {
            this.vertex = vertex;
            this.link = link;
        }
    }
    static void dfs(int index, int depth){
        visited[index] = true;
        if(depth==5){
            answer =1;
            return;
        }
        for(Node next = map[index]; next!=null; next=next.link){
            if(!visited[next.vertex])
                dfs(next.vertex,depth+1);
        }
        visited[index] = false;
    }
    public static int parseTokenToInt(StringTokenizer st){
        return Integer.parseInt(st.nextToken());
    }
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int N =  parseTokenToInt(st), M =  parseTokenToInt(st);
        map = new Node[N];
        visited = new boolean[N];
        int head, next;

        for (int i = 0; i < M; i++) {
            st = new StringTokenizer(br.readLine());
            head =  parseTokenToInt(st);
            next =  parseTokenToInt(st);
            // 같은 관계는 두번 이상 주어지지 않는다.
            map[head] = new Node(next, map[head]);
            map[next] = new Node(head,map[next]);
        }
        // 깊이가 5면 1 아니면 0
        for (int i = 0; i < N; i++) {
            dfs(i,1);
        }
        System.out.println(answer);
    }
}

 

'PS > Gold' 카테고리의 다른 글

[Gold V] 숫자고르기 - 2668 (Java)  (0) 2023.08.21
[Gold IV] 연구소 - 14502 (Java)  (0) 2023.08.20
[Gold IV] 치즈 - 2636 (Java)  (0) 2023.08.20
[Gold V] 공주님을 구해라! - 17836 (Java)  (0) 2023.08.17
[Gold V] 숨바꼭질 3 - 13549 (Java)  (0) 2023.08.16

+ Recent posts