알고리즘/백준

11403번 - 경로 찾기

fleur75 2023. 6. 21. 00:50

1️⃣ Floyd-Warshall

 

✏️ 풀이 과정

문제를 이해하는 게 조금 난해할 수 있는데 유향 그래프가 주어질 때 어떤 경로를 거쳐서라도 특정 점에서 특정 점으로 갈 수 있는지 여부를 표시하라는 뜻입니다. 가령 예제 1의 경우 그래프가 사이클이기 때문에 어떤 점에서도 다른 모든 점으로 갈 수 있습니다.(자기 자신으로도요) 그래서 모든 원소가 1이 됩니다.

 

문제를 해결하기 위해 DFS를 모든 정점마다 돈다고 생각하면 굉장히 중복이 많아집니다. 대신 플로이드-워셜 알고리즘을 응용하면 좀 더 간단하고 빠르게 문제를 해결할 수 있습니다. 원래 해당 알고리즘은 최단 거리를 계산하는 알고리즘이지만 문제에서는 연결되어 있는지의 여부만이 관심사이므로 좀 더 코드를 간단하게 만들 수 있습니다.

 

3중 for문에서 중계지점이 가장 바깥에 있고 중간이 시작점, 가장 안쪽이 끝점입니다. 이 때 시작점에서 중계점으로 가는 길이 있고 중계점에서 끝점으로 가는 길이 있으면 인접 행렬에 1로 표시해주면 됩니다. 기존 거리 계산과 같은 원리로 작동하기 때문에 모든 정점에 대해 연결 여부를 구할 수 있습니다. 알고리즘을 돌리고 인접행렬을 출력하면 문제가 해결됩니다.

 

💻 코드

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

public class Main {
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int N = Integer.parseInt(br.readLine());
		int[][] adjMat = new int[N][N];
		StringTokenizer st;
		for(int i=0;i<N;i++) {
			st = new StringTokenizer(br.readLine());
			for(int j=0;j<N;j++) {
				adjMat[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		for(int k=0;k<N;k++) {
			for(int i=0;i<N;i++) {
				for(int j=0;j<N;j++) {
					if(adjMat[i][k] == 1 && adjMat[k][j] == 1) {
						adjMat[i][j] = 1;
					}
				}
			}
		}
		for(int i=0;i<N;i++) {
			for(int j=0;j<N;j++) {
				System.out.print(adjMat[i][j]+" ");
			}
			System.out.println();
		}
		br.close();
	}
}