Notice
Recent Posts
Recent Comments
Link
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Tags
more
Archives
Today
Total
관리 메뉴

jjj

플로이드 워셜 본문

알고리즘/이론

플로이드 워셜

JJJJ123 2018. 10. 12. 14:17

플로이드 워셜은 모든 점에서 다른 모든 점까지의 최소 거리를 구하는 알고리즘이다.

 

k라는 정점을 정해놓고 모든 점이 그 점을 경유했을 때 다른 모든 점까지의 최소값을 갱신하면서 모든 점 사이의 최소값을 구하는 방법이다. k를 모든 정점에 대해서 수행한다.

 

만약 i 정점에서 k까지 이어져 있지 않다면 j for문을 뛰어넘어도 상관이 없을 것이다.

 

const int MAX_V = 1000;

// 정점의 개수
int V;

// 간선이 없으면 아주 큰 값을 넣는다.
int adj[MAX_V][MAX_V];

void floyd() {
	for (int i = 0; i < V; i++) {
		adj[i][i] = 0;
	}

	for (int k = 0; k < V; k++) {
		for (int i = 0; i < V; i++) {
			for (int j = 0; j < V; j++) {
				adj[i][j] = min(adj[i][j], adj[i][k] + adj[k][j]);
			}
		}
	}
}

 

최단 거리 경로

 

u와 v의 최단 경로를 경유하는 가장 큰점 k에 대해 w에 대해 u ~ w / w ~ v 를 재귀적으로 파고 들어가서 경로를 구한 후 합쳐준다.

// via[u][v] = u 에서 v까지 가는 최단 경로가 경유하는 점 중 가장 번호가 큰 정점
// 처음에 -1로 초기화
int via[MAX_V][MAX_V];

void floyd2() {
	for (int i = 0; i < V; i++) {
		adj[i][i] = 0;
	}

	memset(via, -1, sizeof(via));

	for (int k = 0; k < V; k++) {
		for (int i = 0; i < V; i++) {
			for (int j = 0; j < V; j++) {
				if (adj[i][j] > adj[i][k] + adj[k][j]) {
					via[i][j] = k;
					adj[i][j] = adj[i][k] + adj[k][j];
				}
			}
		}
	}
}

// u에서 v로 가는 최단 경로를 계산해 path에 저장한다.
// u에서 w까지의 거리와 w에서 v까지의 거리를 재귀적으로 구현
void reconstruct(int u, int v, vector<int>& path) {
	if (via[u][v] == -1) {
		path.push_back(u);
		if (u != v) path.push_back(v);
	}
	else {
		int w = via[u][v];
		reconstruct(u, w, path);
		path.pop_back(); // 중복으로 들어가기 때문에
		reconstruct(w, v, path);
	}
}

 

'알고리즘 > 이론' 카테고리의 다른 글

네트워크 유량 ( 포드 풀커슨 )  (0) 2018.10.12
크루스칼 (Kruskal)  (0) 2018.10.12
상호 배타적 조합 ( DisjointSet )  (0) 2018.10.08
SCC(Strongly Connected Component)  (0) 2018.10.08
오일러 회로, 경로  (0) 2018.10.07
Comments