ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 11404 플로이드
    백준/플로이드 워셜 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

     

    댓글

Designed by Tistory.