알고리즘/PS

[C++] 백준 2458 : 키 순서

BigmacGood 2022. 4. 15. 21:57

https://www.acmicpc.net/problem/2458

 

2458번: 키 순서

1번부터 N번까지 번호가 붙여져 있는 학생들에 대하여 두 학생끼리 키를 비교한 결과의 일부가 주어져 있다. 단, N명의 학생들의 키는 모두 다르다고 가정한다. 예를 들어, 6명의 학생들에 대하여

www.acmicpc.net

백준 2458번 키 순서를 풀었다.

 

먼저 플로이드 와샬 알고리즘으로 전체 노드의 비용을 구한다.

예제 1을 인풋으로 넣었을 때 dist배열이다.

  1 2 3 4 5 6
1 0 2 INF 2 1 3
2 INF 0 INF INF INF INF
3 INF 2 0 1 INF 2
4 INF 1 INF 0 INF 1
5 INF 1 INF 1 0 2
6 INF INF INF INF INF 0

 

그 다음 알아볼 노드 i 에 대해서 j 로 가는 경로가 없을 경우 j 를 벡터 v 에 넣는다.

예제에서 4번 노드의 경우 1, 3, 5번 노드로 가는 경로가 없기 때문에 벡터 v에 1, 3, 5 를 넣는다.

2, 4번 노드로 가는 비용이 있기 때문에 2, 4번과는 키를 비교할 수 있다. 따라서 1, 3, 5번 노드와 키를 비교할 수 있다면 4번 노드는 자신의 키가 몇 번째인지 알 수 있다.

 

벡터 v 에 넣어진 j 값들을 하나씩 빼서 j 에서 i 로 가는 경로가 있다면 flag를 1로 유지하고 없다면 flag를 0으로 갱신한다.

벡터를 비울 때 까지 flag가 1로 유지된다면 i 노드는 자신의 키가 몇 번째인지 알 수 있다.

예제의 경우를 살펴보자. 벡터 v에는 1, 3, 5 가 들어있고 하나씩 꺼내서 알아봐야 한다.

1번 노드에서 4번 노드로 가는 비용이 2므로 경로가 있고, 키를 비교할 수 있다.

3번 노드에서 4번 노드로 가는 비용이 1이므로 경로가 있고, 키를 비교할 수 있다.

5번 노드에서 4번 노드로 가는 비용이 1이므로 경로가 있고, 키를 비교할 수 있다.

벡터에 있는 모든 노드들이 4번 노드로 가는 경로가 있으므로 flag는 1로 유지되고 4번 노드는 자신의 키가 몇 번째인지 알 수 있다.

 

 

아래는 전체 코드입니다.

#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
#include <vector>
#pragma warning(disable:4996)
using namespace std;

#define INF 10000000

int adj[501][501];
int dist[501][501];


int main() {
	int n, m;

	cin >> n >> m;

	for (int i = 0; i < m; i++) {
		int small, tall;
		//cin >> small >> tall;
		scanf("%d %d", &small, &tall);
		adj[small][tall] = 1;
	}

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (i == j)
				dist[i][j] = 0;
			else if (adj[i][j] != 0)
				dist[i][j] = adj[i][j];
			else
				dist[i][j] = INF;
		}
	}

	for (int k = 1; k <= n; k++) { // Via node
		for (int i = 1; i <= n; i++) { // Start node
			for (int j = 1; j <= n; j++) { // End node
				dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
			}
		}
	}

	int cnt = 0;
	vector<int> v;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (dist[i][j] == INF)
				v.push_back(j);
		}

		int flag = 1;
		while (!v.empty()) {
			int check = v.back();
			v.pop_back();
			if (dist[check][i] == INF)
				flag = 0;
		}

		if (flag)
			cnt++;
	}

	cout << cnt;

	return 0;
}

 

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

[C++] 백준 10159 : 저울  (0) 2022.04.15
[C++] 백준 1959 : 운동  (0) 2022.04.15
[C++] 백준 11404 : 플로이드  (0) 2022.04.14
[C++] 백준 11403 : 경로 찾기  (0) 2022.04.14
[C++] 백준 3020 : 개똥벌레  (0) 2022.04.13