본문 바로가기
Swexpert/그래프

SW Expert Academy [Professional] 키 순서 / 백준 2458 키 순서

by 29살아저씨 2021. 9. 29.
반응형

🅰 SW Expert Academy [Professional] 키 순서

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

 

 

 

2458번: 키 순서

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

www.acmicpc.net

✏️ 문제 풀이

  • 백준의 키 순서 문제와 동일한 문제이다.
  • 학생들의 키를 비교한 결과가 주어질 때, 자신의 키가 몇 번째인지 알 수 있는 학생들이 모두 몇 명인지 계산하여 출력하는 프로그램을 작성해야 한다.
  • 그래프 형식으로 주어지기 때문에 플로이드-와샬을 이용하여 문제를 풀었다.
  • 입력 데이터를 2차원 map배열에 저장 해주고, 플로이드-와샬을 이용하여 k를 거쳐서 가는 모든 경우의 수에 대해 최신화 시켜주었다.
  • 자신의 키가 몇 번째인지 알 수 있는 학생들의 수를 구하기 위해서는 자기 자신으로 들어오는 그래프 수 + 자신이 가리키는 그래프 수 = 정점수(N)-1이 되어야 한다.
  • 플로이드-와샬을 이용하여 최신화 시켜준 그래프를 돌면서 cnt[]배열에 모든 정점에 대한 그래프 수의 합을 구했다.

✏️ 소스코드

package com.ssafy.swexpert.graph;

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

public class Solution_D4_5643_키순서 {

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		for (int test_case = 1; test_case <= T; test_case++) {
			// 데이터 입력
			int N = Integer.parseInt(br.readLine());
			int M = Integer.parseInt(br.readLine());
			int map[][] = new int[N + 1][N + 1];
			for (int i = 1; i <= N; i++) {
				for (int j = 1; j <= N; j++) {
					if (i == j)	// 자기 자신이면
						map[i][j] = 0; // 갈수없음(0) 저장
					else
						map[i][j] = 100000; // 나머지 큰 값 저장
				}
			}
			for (int i = 1; i <= M; i++) {
				StringTokenizer st = new StringTokenizer(br.readLine());
				int a = Integer.parseInt(st.nextToken());
				int b = Integer.parseInt(st.nextToken());
				map[a][b] = 1;	// a->b 갈 수 있음(1) 표시
			}

			for (int k = 1; k <= N; k++) { // 플로이드-와샬 
				for (int i = 1; i <= N; i++) { 
					for (int j = 1; j <= N; j++) {
						// 모든 케이스에 대해 i에서 j 가는데 k를 거쳐서 가는 경우를 비교하여 더 적은 값 저장
						map[i][j] = Math.min(map[i][j], map[i][k] + map[k][j]);
					}
				}
			}
			
			// 키를 알 수 있는 경우를 구하기 위해서 자기 자신으로 들어오는 그래프 수와, 자기가 가리키는 그래프 수의 합이 N(정점)-1이 되어야 한다.
			int ans = 0; // 자신의 키가 몇번째 인지 아는 학생들의 수
			int cnt[] = new int[N + 1]; // 모든 학생의 들어오는 그래프, 가리키는 그래프 수의 합 저장할 배열
			int self = 0; // 자기자신이 가리키는 그래프 수를 저장할 변수
			for (int i = 1; i <= N; i++) { 
				for (int j = 1; j <= N; j++) {
					if (map[i][j] == 0 || map[i][j] == 100000) // 자기 자신과 연결되어 있지 않은 그래프는 pass
						continue;
					self++; // 자신이 가리키는 그래프 ++
					cnt[j]++; // 자신이 가리키는 그래프++ (상대 입장에서는 들어오는 그래프++)
				}
				cnt[i] += self; // 자신이 가리키는 그래프의 수를 자기자신의 배열에 저장
				self = 0;
			}
			for (int i = 1; i <= N; i++) {
				if (cnt[i] == N - 1) // 자기자신의 연결,가리키는 그래프의 합이 N-1일때 
					ans++; //ans++
			}
			System.out.println("#" + test_case + " " + ans);
		}
	}
}

 

✅ 후기

  • 그래프 문제라는것은 알았지만 어떠한 방식을 이용해서 풀지에 대해 고민을 많이 했다. 이번에 그래프를 공부하면서 그래프를 푸는 방법에 대해 모두 정리하고 어느 문제에 어떤 방식을 이용해야 잘 풀 수 있을지 깨닫도록 노력해야겠다.
반응형

댓글