백준/플로이드 워셜

11404 플로이드

have a good time 2024. 6. 25. 14:49

 

 

 

1. 플로이드 워셜 알고리즘에 대해 설명하자면,

모든 정점에서 모든 정점으로의 최단경로를 구하고 싶을 때 사용한다.

=> 거쳐가는 정점 기준으로 알고리즘 수행

=> 음수 순환 사이클이 없는 그래프에서 수행

 

2. 다익스트라 알고리즘은, 하나의 정점에서 출발하여 다른 모든 정점으로의 최단경로 구함.

 

 

 

 

 

그러면 플로이드 워셜 알고리즘에 대해 알아보자. 

 

1. 첫번째

 

맨 처음에 직행으로 갈 수 있는 경로를 구하면, 아래 표와 같다.

갈 수 있는 경로가 없다면, 무한(큰 값)으로 둔다.

 

1->1,  2->2,  3->3 

즉 본인에서 본인으로 가는 경로는 0으로 한다. 

  1 2 3
1 0 1 1
2 1 0 4
3 5 무한 0

 

 

 

 

2. 두번째 - 정점 1을 경유하여,

위에서 플로이드 워셜 알고리즘은 거쳐가는 정점 기준으로 수행한다고 했다. 

정점을 순서대로 돌아가며, 최단경로를 구한다.

 

정점 1을 경유하는 경우는 아래와 같다.

[1] 3 - 1 - 2

[2] 2 - 1 - 3

 

 

 

[1] 3 - 1 - 2 의 경우 

총 거리가 5 + 1 = 6 이다.

그런데 원래 3 -2 의 경우 무한이므로,

6이 더 작은 값이다. 

 

따라서 무한 -> 6로 바꿔준다. 

 

[2] 2 - 1 - 3 의 경우 

총 거리가 1 + 1 = 2이다.

원래 2 -3 의 경우 4이므로 정점을 지나가는 것이 더 작아서 4-> 2로 바꿔준다 

 

 

  1 2 3
1 0 1 1
2 1 0 4 -> 2
3 5 무한 -> 6 0

 

2. 세번째 - 정점 2를 경유하여,

정점 2를 경유하는 경우는 아래와 같다.

 

 



[1] 1 - 2 - 3

이 경우 총 거리가 1 + 4 = 5 이다.

그런데 1 - 3의 경우 1이므로 원래의 경로가 더 작다.

바꿔줄 것 없이 그냥 넘어가면 된다. 

 

  1 2 3
1 0 1 1
2 1 0 2
3 5 6 0

 

2. 네번째 - 정점 3을 경유하여,

 

 

 

이 경우는 

[1] 2 - 3 - 1 

 

[1] 의 경우 총 경로가 4 + 5 = 9

2 - 1 의 경로는 1이므로 원래 경로가 더 작다.

그러므로 그냥 유지하면 된다. 

 

  1 2 3
1 0 1 1
2 1 0 2
3 5 6 0

 

 

이런식으로 해결하면 된다. 

 

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

public class Main {	
	
	private static final int max = Integer.MAX_VALUE;
	
	public static void main(String[] args) throws IOException {		
	
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int n = Integer.parseInt(st.nextToken());

		st = new StringTokenizer(br.readLine(), " ");
		int m  = Integer.parseInt(st.nextToken());
		
		int bus[][] = new int [n+1][n+1];
		
		for(int i=1; i<=n; i++) {			
			for(int j = 1; j<=n; j++) {
				
				if(i==j) {						
					bus[i][j] = 0;						
					
				}else {									
					bus[i][j] = max;
					
				}
			}			
		}	
		
		for(int i=0; i<m; i++) {
			
			 st = new StringTokenizer(br.readLine(), " ");
			 int a = Integer.parseInt(st.nextToken());
			 int b = Integer.parseInt(st.nextToken());
			 int c= Integer.parseInt(st.nextToken());			 
	
			 bus[a][b] = Math.min(c, bus[a][b]);
			
			
		}	
	
		
		for(int i=1; i<=n; i++) {
			for(int j =1; j<=n; j++) {
				for(int k =1; k<=n; k++) {
					
					if(bus[j][i]!=max && bus[i][k]!= max ) {
					bus[j][k] = Math.min(bus[j][k], bus[j][i] + bus[i][k]);
					
					}					
				}			
			}			
		}
		
		
		
		for(int i=1; i<=n ; i++) {
			for(int j = 1; j<=n ; j++) {
				
				int value = bus[i][j];
				
				if(value==max) {
					value = 0;
				}
				
				System.out.print(value + " ");
			}System.out.println();
		}
		
	
	
	}
	
	
	
}

 

 

 

 

 

 

 

 

 

참고 블로그 : 

https://blog.naver.com/ndb796/221234427842

 

24. 플로이드 와샬(Floyd Warshall) 알고리즘

  지난 시간에는 다익스트라(Dijkstra) 알고리즘에 대해 학습했습니다. 다익스트라 알고리즘은 하나...

blog.naver.com

 

https://olrlobt.tistory.com/43

 

[알고리즘] Floyd-Warshall Algorithm : 플로이드 워셜 알고리즘이란?

플로이드 워셜 알고리즘 (Floyd-Warshall Algorithm) Floyd-Warshall 알고리즘은 음수 순환 사이클이 없는 그래프에서, 모든 점에서 모든 점까지의 최단거리를 구하는 알고리즘이다. 한 점에서 이웃 노드를

olrlobt.tistory.com