본문 바로가기
Problem Solving/Baekjoon

[백준] 1389 케빈 베이컨의 6단계 법칙 - Graph Theory / Java

by graycode 2022. 8. 22.

 문제 링크

 

1389번: 케빈 베이컨의 6단계 법칙

첫째 줄에 유저의 수 N (2 ≤ N ≤ 100)과 친구 관계의 수 M (1 ≤ M ≤ 5,000)이 주어진다. 둘째 줄부터 M개의 줄에는 친구 관계가 주어진다. 친구 관계는 A와 B로 이루어져 있으며, A와 B가 친구라는 뜻

www.acmicpc.net

 

 풀이 과정

 

[백준] 11404 플로이드 - Graph Theory / Java

• 문제 링크 11404번: 플로이드 첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는

graycode.tistory.com

위 문제와 유사한 구조의 Floyd-Warshall 알고리즘 문제이다.

 

모든 노드간 최단 경로를 구하되, 노드간 몇 번 이동했는지만 구하면 되므로

무향 그래프의 가중치를 1로 지정하여 각 경로의 최소 이동 횟수를 구한다.

 

이 후 각각의 노드를 시작점으로 하는 모든 경로의 이동 횟수의 합을 최소값으로 갱신하고,

해당 노드의 번호를 정답으로써 출력한다.

 

 풀이 코드

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

public class Main {

    static int n;
    static int[][] dist;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());

        n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());
        dist = new int[n + 1][n + 1];

        int inf = 5001;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (i == j)
                    continue;
                else
                    dist[i][j] = inf;
            }
        }

        for (int i = 0; i < m; i++) {
            st = new StringTokenizer(br.readLine());
            int src = Integer.parseInt(st.nextToken());
            int dest = Integer.parseInt(st.nextToken());

            dist[src][dest] = dist[dest][src] = 1;
        }

        floydWarshall();

        int minCnt = inf;
        int res = 0;
        for (int i = 1; i <= n; i++) {
            int cnt = 0;
            for (int j = 1; j <= n; j++)
                cnt += dist[i][j];

            if (minCnt > cnt) {
                minCnt = cnt;
                res = i;
            }
        }

        bw.write(res + "\n");
        bw.flush();
    }

    private static void floydWarshall() {
        for (int k = 1; k <= n; k++) {
            for (int i = 1; i <= n; i++) {
                if (i == k)
                    continue;

                for (int j = 1; j <= n; j++) {
                    if (j == i || j == k)
                        continue;
                    if (dist[i][j] > dist[i][k] + dist[k][j])
                        dist[i][j] = dist[i][k] + dist[k][j];
                }
            }
        }
    }

}

 

아래의 코드는 BFS 를 통한 풀이로,

Queue 를 통해 특정 시작점에서 파생될 수 있는 모든 경로를 방문 여부를 확인하며 탐색한다.

이렇게 총 이동 횟수를 누적 및 반환하고, 이 중 최소 이동 횟수를 가지는 노드의 번호를 정답으로써 출력한다.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {

    static int[] dist;
    static List<Integer>[] list;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());

        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());

        dist = new int[n + 1];
        list = new ArrayList[n + 1];

        for (int i = 1; i <= n; i++)
            list[i] = new ArrayList<>();

        for (int i = 0; i < m; i++) {
            st = new StringTokenizer(br.readLine());
            int src = Integer.parseInt(st.nextToken());
            int dest = Integer.parseInt(st.nextToken());

            list[src].add(dest);
            list[dest].add(src);
        }

        int minCnt = Integer.MAX_VALUE;
        int res = 0;
        for (int i = 1; i <= n; i++) {
            int cnt = bfs(i);

            if (minCnt > cnt) {
                minCnt = cnt;
                res = i;
            }
        }

        bw.write(res + "\n");
        bw.flush();
    }

    private static int bfs(int source) {
        Queue<Integer> q = new LinkedList<>();

        q.offer(source);
        Arrays.fill(dist, -1);
        dist[source] = 0;

        int cnt = 0;
        while (!q.isEmpty()) {
            int src = q.poll();
            for (int dest : list[src]) {
                if (dist[dest] != -1)
                    continue;

                dist[dest] = dist[src] + 1;
                cnt += dist[dest];

                q.offer(dest);
            }
        }

        return cnt;
    }

}

댓글