최단 경로 - 2. 정확한 순위

LEE ·2022년 5월 11일
0

알고리즘 기출문제

목록 보기
38/60

문제

선생님은 시험을 본 학생 N명의 성적을 분실하고, 성적을 비교한 결과의 일부만 가지고 있다. 학생 N명의 성적은 모두 다른데, 다음은 6명의 학생에 대하여 6번만 성적을 비교한 결과이다.

1번 학생의 성적 < 5번 학생의 성적
3번 학생의 성적 < 4번 학생의 성적
4번 학생의 성적 < 2번 학생의 성적
4번 학생의 성적 < 6번 학생의 성적
5번 학생의 성적 < 2번 학생의 성적
5번 학생의 성적 < 4번 학생의 성적

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(2 <= M <= 10,000)이 주어진다.
다음 M개의 각 줄에는 두 학생의 성적을 비교한 결과를 나타내는 두 양의 정수 A와 B가 주어진다. 이는 A번 학생의 성적이 B번 학생보다 낮다는 것을 의미한다.

출력 조건
첫째 줄에 성적 순위를 정확히 알 수 있는 학생이 몇 명인지 출력한다.

입력 예시

6 6
1 5
3 4
4 2
4 6
5 2
5 4

출력 예시

1

구현코드

import java.io.*;
import java.util.*;

public class Main {

	public static int INF = (int)1e9;
	public static void main(String[] args)throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		int[][] d = new int[n+1][n+1];
		for(int i = 0 ; i <= n ; i++){
			Arrays.fill(d[i] ,INF);
		}
		for(int i = 1; i <= n ; i++){
			for(int j = 1; j <= n ; j++){
				if(i == j) d[i][j] = 0;
			}
		}
		for(int i = 0; i < m; i++){
			st = new StringTokenizer(br.readLine());
			int x = Integer.parseInt(st.nextToken());
			int y = Integer.parseInt(st.nextToken());
			d[x][y] = 1;
		}
		for(int k = 1; k <= n ; k++){
			for(int i = 0; i <= n ; i++){
				for(int j = 1; j <= n ; j++){
					d[i][j] = Math.min(d[i][j], d[i][k] + d[k][j]);
				}
			}
		}
		int result = 0;
		for(int i = 1; i <= n ; i++){
			int cnt = 0;
			for(int j = 1; j <= n; j++){
				if(d[i][j] != INF || d[j][i] != INF){
					cnt++;
				}
			}
			if(cnt  == n) result++;
		}
		System.out.println(result);
	}

}

코드해석

이 문제는 플로이드 워셜 알고리즘을 사용하여 구현 한 후에

		for(int i = 1; i <= n ; i++){
			int cnt = 0;
			for(int j = 1; j <= n; j++){
				if(d[i][j] != INF || d[j][i] != INF){
					cnt++;
				}
			}
			if(cnt  == n) result++;
		}

이 코드가 중요한 것이다. 가로 세로를 본 후에 cnt 해주고 그 cnt 가 n 값이 될 때를 확인하면 된다.

0개의 댓글

관련 채용 정보