[코딩테스트] MooTube (BFS)

최지나·2024년 5월 6일
2

코딩테스트

목록 보기
150/154

문제

농부 존은 남는 시간에 MooTube라 불리는 동영상 공유 서비스를 만들었다. MooTube에서 농부 존의 소들은 재밌는 동영상들을 서로 공유할 수 있다. 소들은 MooTube에 1부터 N까지 번호가 붙여진 N (1 ≤ N ≤ 5,000)개의 동영상을 이미 올려 놓았다. 하지만, 존은 아직 어떻게 하면 소들이 그들이 좋아할 만한 새 동영상을 찾을 수 있을지 괜찮은 방법을 떠올리지 못했다.

농부 존은 모든 MooTube 동영상에 대해 “연관 동영상” 리스트를 만들기로 했다. 이렇게 하면 소들은 지금 보고 있는 동영상과 연관성이 높은 동영상을 추천 받을 수 있을 것이다.

존은 두 동영상이 서로 얼마나 가까운 지를 측정하는 단위인 “USADO”를 만들었다. 존은 N-1개의 동영상 쌍을 골라서 직접 두 쌍의 USADO를 계산했다. 그 다음에 존은 이 동영상들을 네트워크 구조로 바꿔서, 각 동영상을 정점으로 나타내기로 했다. 또 존은 동영상들의 연결 구조를 서로 연결되어 있는 N-1개의 동영상 쌍으로 나타내었다. 좀 더 쉽게 말해서, 존은 N-1개의 동영상 쌍을 골라서 어떤 동영상에서 다른 동영상으로 가는 경로가 반드시 하나 존재하도록 했다. 존은 임의의 두 쌍 사이의 동영상의 USADO를 그 경로의 모든 연결들의 USADO 중 최솟값으로 하기로 했다.

존은 어떤 주어진 MooTube 동영상에 대해, 값 K를 정해서 그 동영상과 USADO가 K 이상인 모든 동영상이 추천되도록 할 것이다. 하지만 존은 너무 많은 동영상이 추천되면 소들이 일하는 것이 방해될까 봐 걱정하고 있다! 그래서 그는 K를 적절한 값으로 결정하려고 한다. 농부 존은 어떤 K 값에 대한 추천 동영상의 개수를 묻는 질문 여러 개에 당신이 대답해주기를 바란다.

입력

입력의 첫 번째 줄에는 N과 Q가 주어진다. (1 ≤ Q ≤ 5,000)

다음 N-1개의 줄에는 농부 존이 직접 잰 두 동영상 쌍의 USADO가 한 줄에 하나씩 주어진다. 각 줄은 세 정수 pi, qi, ri (1 ≤ pi, qi ≤ N, 1 ≤ ri ≤ 1,000,000,000)를 포함하는데, 이는 동영상 pi와 qi가 USADO ri로 서로 연결되어 있음을 뜻한다.

다음 Q개의 줄에는 농부 존의 Q개의 질문이 주어진다. 각 줄은 두 정수 ki와 vi(1 ≤ ki ≤ 1,000,000,000, 1 ≤ vi ≤ N)을 포함하는데, 이는 존의 i번째 질문이 만약 K = ki라면 동영상 vi를 보고 있는 소들에게 몇 개의 동영상이 추천될 지 묻는 것이라는 것을 뜻한다.

출력

Q개의 줄을 출력한다. i번째 줄에는 농부 존의 i번째 질문에 대한 답변이 출력되어야 한다.

예제 입력 1

4 3
1 2 3
2 3 2
2 4 4
1 2
4 1
3 1

예제 출력 1

3
0
2

생각

  • 특정 동영상과 연관 동영상은 USADO 라는 측정값에 의해 연결됨으로 이 정보 즉 weight 를 담을 수 있게 새로운 class Edge 를 선언하였다. 연관 동영상의 번호 즉 node와 연관성 weight를 담고 있다.
  • 동영상이 조건을 만족하는지 시작 노드로부터 점점 먼 거리로 나가며 탐색하기 때문에 BFS의 사용이 적합하다고 판단하였다.
  • 인접 행렬을 사용하기에는 N의 범위가 5000까지 커질 수 있기 때문에 메모리의 낭비가 커서 인접 리스트를 사용하였다.

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;

public class MooTube {

    static class Edge {
        private int node;
        private int weight;

        Edge(int node, int weight) {
            this.node = node;
            this.weight = weight;
        }
    }

    public int BFS(ArrayList<ArrayList<Edge>> graph, int N, int V, int K) {
        boolean[] visited = new boolean[N + 1];
        Queue<Integer> queue = new LinkedList<>();
        queue.add(V);
        visited[V] = true;
        int cnt = 0;

        while (!queue.isEmpty()) {
            int cur = queue.poll();

            for (Edge edge : graph.get(cur)) {
                if (!visited[edge.node] && edge.weight >= K) {
                    queue.add(edge.node);
                    visited[edge.node] = true;
                    cnt++;
                }
            }
        }
        return cnt;
    }

    public static void main(String[] args) throws IOException {
        MooTube T = new MooTube();
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int[] nums = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();

        int N = nums[0];
        int Q = nums[1];

        ArrayList<ArrayList<Edge>> graph = new ArrayList<>();

        for (int i = 0; i <= N; i++) {
            graph.add(new ArrayList<Edge>());
        }

        for (int i = 0; i < N - 1; i++) {
            int[] tmp = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();

            graph.get(tmp[0]).add(new Edge(tmp[1], tmp[2]));
            graph.get(tmp[1]).add(new Edge(tmp[0], tmp[2]));
        }

        for (int i = 0; i < Q; i++) {
            int[] questions = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();

            int K = questions[0];
            int V = questions[1];

            System.out.println(T.BFS(graph, N, V, K));
        }
    }
}


문제 출처

profile
의견 나누는 것을 좋아합니다 ლ(・ヮ・ლ)

1개의 댓글

comment-user-thumbnail
2024년 5월 9일

소들이 호강하네요 잘봤습니다

답글 달기