Floyd Warshall Algorithm

  1. 모든 정점 –> 모든 정점으로 가는 모든 경우의 수를 2차원 배열에 저장
  2. 기존의 경로 값 vs 특정 노드를 거치는 경우 경로 값 비교 뒤 더 작은거 저장


참고 자료
https://www.youtube.com/watch?time_continue=879&v=9574GHxCbKc&feature=emb_logo


백준 11403


그냥 for문을 통해 플로이드 와샬 알고리즘을 작성하라는 뜻이다



모든 정점에서 정점으로 가는 모든 경우의 수를 비교하는 것이므로
if 조건으로 x[j][k] == 0이면 하지 마라 이런거 할 필요 X



public class Main {

public static void main(String[] args) throws NumberFormatException, IOException {
	
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
	StringTokenizer st;
	
	int n = Integer.parseInt(br.readLine()); // 첫번째로 받은 인자 String 타입을 int로 변환해 저장
	int[][] temp = new int[n][n];
	
	// 두번째로 받은 파라미터 문자열을 쪼개서 배열로 저장
	for(int i=0; i<n; i++) {
		
		// scanner든 buffer든 항상 한 줄 단위로 입력됨!!
		// 그래서 첫 로우를 첫번째 루프에서 읽는다
		st = new StringTokenizer(br.readLine());
		
		for(int j=0; j<n; j++) {
			// 받은 첫 로우를 .nextToken을 통해 잘라서 각각 answer에 저장
			temp[i][j] = Integer.parseInt(st.nextToken());
		}
	}
	
	// 모든 정점들을 비교한 뒤 최소값을 넣는 answer 배열 생성
	/*
	 * int[][] answer = new int[n][n];
	 * 
	 * for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { answer[i][j] = 99999999; }
	 * }
	 */
	
	// temp에서 모든 정점들에서 정점으로 가는 경우의 수(경로 값 비교)
	for(int i=0; i<n; i++) { // 거치는 노드
		for(int j=0; j<n; j++) { // 출발 노드
			for(int k=0; k<n; k++) { // 도착 노드
				if(temp[j][i] + temp[i][k] < temp[j][k]) {
					temp[j][k] = temp[j][i] + temp[i][k];
				}
			}
		}
	}
	
	// 답 출력
	StringBuilder sb = new StringBuilder();
	for(int i=0; i<n; i++) {
		for(int j=0; j<n; j++) {
			sb.append(temp[i][j] + " ");
		}
		sb.append("\n");
	}
	
	bw.write(sb.toString());
	bw.flush();
	bw.close();
	br.close();
}	 } ``` 틀림   맞는거같은데 왜인가 참고하는 코드를 보고 예제도 봤다   정석대로의 플루이드 알고리즘 아닌가?   예제를 보니까 아니었다   문제 좀 똑바로 읽자...  


image
만약에 가는 경로가 있다면 1, 없다면 0임을 누가봐도 알 수 있다^^..
즉 내 코드로 치환하자면
출발하는 j노드에서 도착지점인 k노드에 갈 때,
j👉i👉k 혹은 k👉i👉j가 가능하다면 temp에 1을 집어넣는다


public class Main {

public static void main(String[] args) throws NumberFormatException, IOException {
	
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
	StringTokenizer st;
	
	int n = Integer.parseInt(br.readLine()); // 첫번째로 받은 인자 String 타입을 int로 변환해 저장
	int[][] temp = new int[n][n];
	
	// 두번째로 받은 파라미터 문자열을 쪼개서 배열로 저장
	for(int i=0; i<n; i++) {
		
		// scanner든 buffer든 항상 한 줄 단위로 입력됨!!
		// 그래서 첫 로우를 첫번째 루프에서 읽는다
		st = new StringTokenizer(br.readLine());
		
		for(int j=0; j<n; j++) {
			// 받은 첫 로우를 .nextToken을 통해 잘라서 각각 answer에 저장
			temp[i][j] = Integer.parseInt(st.nextToken());
		}
	}

	
	// temp에서 모든 정점들에서 정점으로 가는 경우의 수(경로 값 비교)
	for(int i=0; i<n; i++) { // 거치는 노드
		for(int j=0; j<n; j++) { // 출발 노드
			for(int k=0; k<n; k++) { // 도착 노드
				if(temp[j][i] == 1 || temp[i][k] == 1) {
					temp[j][k] = 1;
				}
			}
		}
	}
	
	// 답 출력
	StringBuilder sb = new StringBuilder();
	for(int i=0; i<n; i++) {
		for(int j=0; j<n; j++) {
			sb.append(temp[i][j] + " ");
		}
		sb.append("\n");
	}
	
	bw.write(sb.toString());
	bw.flush();
	bw.close();
	br.close();
}	 } ``` 또 틀렸다  



j👉i👉k 혹은 k👉i👉j가 가능하다면 temp에 1을 집어넣고 아니면 0이다
틀림ㅋㅋ
둘 중 하나만 가능하면 전부 왔다갔다가 안되니까…
서로 왕복이 되는 경우였음 예제 2보니까
image image
만약 둘 중 하나라도 경로가 있는데 1이라면
노드 3에도 1이 들어가야함 (7–>3)
하지만 0인걸 보면 쌍방으로 이동 가능해야만 1을 추가할 수 있음


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

public class Main {

	public static void main(String[] args) throws NumberFormatException, IOException {
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringTokenizer st;
		
		int n = Integer.parseInt(br.readLine()); // 첫번째로 받은 인자 String 타입을 int로 변환해 저장
		int[][] temp = new int[n][n];
		
		// 두번째로 받은 파라미터 문자열을 쪼개서 배열로 저장
		for(int i=0; i<n; i++) {
			
			// scanner든 buffer든 항상 한 줄 단위로 입력됨!!
			// 그래서 첫 로우를 첫번째 루프에서 읽는다
			st = new StringTokenizer(br.readLine());
			
			for(int j=0; j<n; j++) {
				// 받은 첫 로우를 .nextToken을 통해 잘라서 각각 answer에 저장
				temp[i][j] = Integer.parseInt(st.nextToken());
			}
		}

		
		// temp에서 모든 정점들에서 정점으로 가는 경우의 수(경로 값 비교)
		for(int i=0; i<n; i++) { // 거치는 노드
			for(int j=0; j<n; j++) { // 출발 노드
				for(int k=0; k<n; k++) { // 도착 노드
					if(temp[j][i] == 1 && temp[i][k] == 1) {
						temp[j][k] = 1;
					}
				}
			}
		}
		
		// 답 출력
		StringBuilder sb = new StringBuilder();
		for(int i=0; i<n; i++) {
			for(int j=0; j<n; j++) {
				sb.append(temp[i][j] + " ");
			}
			sb.append("\n");
		}
		
		bw.write(sb.toString());
		bw.flush();
		bw.close();
		br.close();
	}	
}

image


기타 질문

사바사겠지만 연습장에 손으로 풀면서 문제 푸는거보다
컴퓨터에 타자치며 코테 진행하는 것이 더 나은지??
이런 노드 탐색은 손으로 노드 그리는거 아니면 어떻게 푸는지?????