1 분 소요

문제

N명의 학생 간 성적을 비교한 결과 중 일부만 가지고 있다.

A번 학생이 성적이 B번 학생보다 낮다면,

화살표가 A에서 B를 가리키도록 할 때 성적 순위를 알 수 있는 학생은 모두 몇 명?


핵심 아이디어
  • 화살표로 가리킨다는 점에서 성적 비교 결과는 ‘방향 그래프’로 볼 수 있다.

  • 핵심은, A에서 B로 도달이 가능하거나 B에서 A로 도달 가능하면 ‘성적비교 가능’이라는 점이다.

  • 성적 순위를 알 수 있으려면 다른 모든 학생과의 성적 비교가 가능해야한다.
  • 즉, 각 노드를 차례로 검사하며 다른 모든 노드와의 연결된 경로가 있는지 확인한다


로직

최단경로 : Floyd-Warshall 알고리즘

Floyd-Warshall 알고리즘을 사용해 모든 노드들간의 최단 경로를 구하고,

각 노드에서 다른 노드로, 또는 다른 노드에서 해당 노드로의 경로 존재 여부를 확인하고

모든 노드에 대해 경로가 존재하면 결과++


시간 복잡도

O(500^3)

N의 크기가 500으로 작으므로, O(N^3)인 플로이드 워셜 알고리즘을 사용해도 된다.


코드 (Java)
package shortestPath;

import java.util.Arrays;
import java.util.Scanner;

public class 정확한순위 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in) ; 
		int n = sc.nextInt() ; 
		int m = sc.nextInt() ;

		// 1. 방향 그래프로 간주 
		// 2. 한 노드에서 다른 노드 각각으로 올 수 있는, 
		// 	또는 갈 수 있는 경로가 다른 노드들 모두에 존재한다면, 해당 학생은 순위를 알 수 있다 

		int[][] graph = new int[n+1][n+1] ;

		// 그래프 만들기 
		for(int i = 1 ; i <= n ; i++) {
			Arrays.fill(graph, 100000);
		}
		for(int i = 0 ; i < m ; i++) {
			int a = sc.nextInt() ; 
			int b = sc.nextInt() ; 
			graph[a][b] = 1 ; // 경로 존재 
		}

		
		// 알고리즘 수행 (점화식) 
		for(int k = 1 ; k <= n ; k++) { 
			for(int i = 1 ; i <= n ; i++) { 
				for(int j = 1 ; j <= n ; j++) {
					graph[i][j] = Math.min(graph[i][j], graph[i][k]+graph[k][j]) ; 
				}
			}
		}

		// answer 도출 
		int answer = 0 ;
		for(int i = 1 ; i <= n ; i++) {
			int count = 0 ;
			for(int j = 1 ; j <= n ; j++) {
				if(graph[i][j] != 100000 || graph[j][i] != 100000) 
					count ++ ; 
			}
			if(count == n) {
				answer++ ; 
			}
		}
		System.out.println(answer);
	}
}


댓글남기기