Home [백준 10159번] 저울 [C언어]
Post
Cancel

[백준 10159번] 저울 [C언어]

10159번: 저울

문제 링크: 10159번: 저울


개요

어떤 정점에서 다른 정점으로 가는 최단경로를 알고 싶을 때 사용하는 알고리즘은 대표적으로 다익스트라(Dijkstra) 알고리즘과 플로이드 와샬(Floyd–Warshall) 알고리즘이 있다. 플로이드 와샬 알고리즘은 3중 반복문을 사용하기 때문에 우선순위 큐를 사용하지 않는 다익스트라 알고리즘의 시간복잡도(O(n²))보다도 더 큰 시간복잡도(O(n³))를 갖는다. 하지만 한 정점에서부터의 최단경로를 알게 되는 다익스트라 알고리즘과는 달리 모든 정점에서 모든 정점으로의 최단 경로를 알 수 있다는 장점이 있다. 이 문제에서는 모든 정점에 대해 최단 경로를 알 수 있는 정점 개수를 각각 출력해야 하기 떄문에 플로이드 와샬 알고리즘이 적합하다.


플로이드 와샬

2차원 배열 dist[i][j]는 i에서 j로 가는 최단 경로를 저장하는 것이 아니라, i가 j보다 무거우면 1, 가벼우면 -1, 알 수 없으면 0을 저장했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	for (int i = 0; i < m; i++) {
		int a, b;
		scanf("%d %d", &a, &b);
		dist[a][b] = 1, dist[b][a] = -1;
	}

	for (int k = 1; k <= n; k++) {
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				if (dist[i][k] && dist[i][k] == dist[k][j]) {
					dist[i][j] = dist[i][k];
				}
			}
		}
	}

k를 거쳐서 i와 j를 비교할 때, w(i) < w(k) < w(j) 이거나 w(i) > w(k) > w(j) 이어야만 w(i)와 w(j)의 대소관계를 알 수 있다. 따라서 dist[i][k]와 dist[k][j]가 같은 경우에만 dist[i][j]를 갱신해주었다. (w(n) = n의 무게)


전체 코드

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
31
32
33
34
35
36
#include <stdio.h> 
#include <string.h> 
#pragma warning(disable:4996)
#pragma warning(disable:6031)

#define MAX_N 100

int main() {
	int n, m, dist[MAX_N+1][MAX_N+1] = { 0 };
	scanf("%d %d", &n, &m);
	for (int i = 0; i < m; i++) {
		int a, b;
		scanf("%d %d", &a, &b);
		dist[a][b] = 1, dist[b][a] = -1;
	}

	for (int k = 1; k <= n; k++) {
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				if (dist[i][k] && dist[i][k] == dist[k][j]) {
					dist[i][j] = dist[i][k];
				}
			}
		}
	}

	for (int i = 1; i <= n; i++) {
		int crCnt = 0;
		for (int j = 1; j <= n; j++) {
			if (!dist[i][j]) crCnt++;
		}
		printf("%d\n", crCnt - 1);
	}

	return 0;
}

This post is licensed under CC BY 4.0 by the author.

[백준 17822번] 원판 돌리기 [C언어]

[Unity] 객체 지향과 유니티 기초 개념