문제
1번부터 N번까지 번호가 붙여져 있는 학생들에 대하여 두 학생끼리 키를 비교한 결과의 일부가 주어져 있다. 단, N명의 학생들의 키는 모두 다르다고 가정한다. 예를 들어, 6명의 학생들에 대하여 6번만 키를 비교하였고, 그 결과가 다음과 같다고 하자.
- 1번 학생의 키 < 5번 학생의 키
- 3번 학생의 키 < 4번 학생의 키
- 5번 학생의 키 < 4번 학생의 키
- 4번 학생의 키 < 2번 학생의 키
- 4번 학생의 키 < 6번 학생의 키
- 5번 학생의 키 < 2번 학생의 키
이 비교 결과로부터 모든 학생 중에서 키가 가장 작은 학생부터 자신이 몇 번째인지 알 수 있는 학생들도 있고 그렇지 못한 학생들도 있다는 사실을 아래처럼 그림을 그려 쉽게 확인할 수 있다. a번 학생의 키가 b번 학생의 키보다 작다면, a에서 b로 화살표를 그려서 표현하였다.
1번은 5번보다 키가 작고, 5번은 4번보다 작기 때문에, 1번은 4번보다 작게 된다. 그러면 1번, 3번, 5번은 모두 4번보다 작게 된다. 또한 4번은 2번과 6번보다 작기 때문에, 4번 학생은 자기보다 작은 학생이 3명이 있고, 자기보다 큰 학생이 2명이 있게 되어 자신의 키가 몇 번째인지 정확히 알 수 있다. 그러나 4번을 제외한 학생들은 자신의 키가 몇 번째인지 알 수 없다.
학생들의 키를 비교한 결과가 주어질 때, 자신의 키가 몇 번째인지 알 수 있는 학생들이 모두 몇 명인지 계산하여 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 학생들의 수 N (2 ≤ N ≤ 500)과 두 학생 키를 비교한 횟수 M (0 ≤ M ≤ N(N-1)/2)이 주어진다.
다음 M개의 각 줄에는 두 학생의 키를 비교한 결과를 나타내는 N보다 작거나 같은 서로 다른 양의 정수 a와 b가 주어진다. 이는 번호가 a인 학생이 번호가 b인 학생보다 키가 작은 것을 의미한다.
출력
자신이 키가 몇 번째인지 알 수 있는 학생이 모두 몇 명인지를 출력한다.
예제 입력 1 복사
6 6
1 5
3 4
5 4
4 2
4 6
5 2
예제 출력 1 복사
1
예제 입력 2 복사
6 7
1 3
1 5
3 4
5 4
4 2
4 6
5 2
예제 출력 2 복사
2
예제 입력 3 복사
6 3
1 2
2 3
4 5
예제 출력 3 복사
0
기본 플로이드 워셜 알고리즘이었으나 정방향과 역방향으로 모두 연결 되어있는지 확인하는 부분이 어려웠던 문제이다.
풀이의 종류는 두 가지가 있다.
1. 최단거리를 구하지 않고 정방향과 역방향으로 boolean값을 이용하여 연결 가능하면 true를 주고 true인 값의 개수가 n과 같을 때 정답 카운트를 올리는 방식
2. 최단거리를 구하고 정방향과 역방향 둘 중 하나가 INF가 아니라면 카운트를 올려주고 카운트가 n과 같을 때 정답 카운트를 올리는 방식
1번 풀이
import java.io.*;
import java.sql.Array;
import java.util.*;
import java.util.stream.Collectors;
public class Main {
private static boolean[][] graph = new boolean[501][501];
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Scanner sc = new Scanner(System.in);
int n, m;
n = sc.nextInt();
m = sc.nextInt();
for(int i=0; i<m; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
graph[a][b] = true;
}
for(int k=1; k<=n; k++) {
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
if(graph[i][k] && graph[k][j]) {
graph[i][j] = true;
}
}
}
}
int[] cnt = new int[n+1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
// i->j 정방향 || j -> i 역방향
if (graph[i][j] || graph[j][i]) {
cnt[i]++;
}
}
}
int res = 0;
for (int num : cnt) {
if (num == n - 1) {
res++;
}
}
System.out.println(res);
}
}
2번 풀이 (블로그 참고 / https://subbak2.com/52)
import java.io.*;
import java.util.*;
// 백준 2458 키순서
public class Main {
static int N, M; // N : 학생의 수 / M : 연산의 수
static int a, b; // input 받는 학생 a, b
static int[][] dist; // floyd-warshall을 위한 2차원 배열
static final int INF = 999999999; // 초기화를 위한 불가능한 최댓값
static int ans; // 출력할 정답
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
// 1. 2차원 배열에 INF (최댓값)으로 초기화
dist = new int [N+1][N+1];
for (int i=1; i<=N; i++) {
for (int j=1; j<=N; j++) {
dist[i][j] = INF;
}
}
// 2. 입력 : a - b 학생의 키 순서를 아는 경우 1로 거리 배열 입력
for (int i = 1; i<= M; i++) {
st = new StringTokenizer(br.readLine());
a = Integer.parseInt(st.nextToken());
b = Integer.parseInt(st.nextToken());
dist[a][b] = 1;
}
// 3. 특정 학생이 모든 학생과의 거리를 체크해야하므로 플로이드 워셜 수행
// 플로이드-워셜 : 경유지 - 출발지 - 도착지 3중 for문
for (int k = 1; k <= N; k++) {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
// dist[i][j]보다 작은 값 나올 경우 갱신
dist[i][j] = dist[i][j] <= dist[i][k] + dist[k][j] ? dist[i][j] : dist[i][k] + dist[k][j];
}
}
}
// 4. 모든 학생과의 비교가 가능한 경우
// → 거리가 INF 가 아닌 학생의 수가 N-1인 경우 : 키가 몇번째인지 알 수 있으므로 ans++
ans = 0;
for (int i = 1; i<=N; i++) {
int cnt = 0;
for (int j=1; j<=N; j++) {
if (dist[i][j] != INF || dist[j][i] != INF ) cnt++;
}
if (cnt == N-1) ans++;
}
bw.write(String.valueOf(ans));
bw.flush();
br.close();
bw.close();
}
}
'Algorythms' 카테고리의 다른 글
백준 13141번 Ignition c++ 풀이 (4) | 2023.11.23 |
---|---|
백준 1389번 케빈 베이커의 6단계 법칙 풀이 java (2) | 2023.11.22 |
백준 11404번 플로이드 java 풀이 (1) | 2023.11.20 |
백준 21278번 호석이 두 마리 치킨 java 풀이 (0) | 2023.11.17 |
백준 11908번 카드 java 풀이 (0) | 2023.11.17 |