백준

[백준_2644번] 촌수계산

빙수빈수 2021. 8. 17. 18:41

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

 

2644번: 촌수계산

사람들은 1, 2, 3, …, n (1 ≤ n ≤ 100)의 연속된 번호로 각각 표시된다. 입력 파일의 첫째 줄에는 전체 사람의 수 n이 주어지고, 둘째 줄에는 촌수를 계산해야 하는 서로 다른 두 사람의 번호가 주어

www.acmicpc.net

[문제]

 우리 나라는 가족 혹은 친척들 사이의 관계를 촌수라는 단위로 표현하는 독특한 문화를 가지고 있다. 이러한 촌수는 다음과 같은 방식으로 계산된다. 기본적으로 부모와 자식 사이를 1촌으로 정의하고 이로부터 사람들 간의 촌수를 계산한다. 예를 들면 나와 아버지, 아버지와 할아버지는 각각 1촌으로 나와 할아버지는 2촌이 되고, 아버지 형제들과 할아버지는 1촌, 나와 아버지 형제들과는 3촌이 된다.

여러 사람들에 대한 부모 자식들 간의 관계가 주어졌을 때, 주어진 두 사람의 촌수를 계산하는 프로그램을 작성하시오.

 

[입력 조건]

 사람들은 1, 2, 3, …, n (1 ≤ n ≤ 100)의 연속된 번호로 각각 표시된다. 입력 파일의 첫째 줄에는 전체 사람의 수 n이 주어지고, 둘째 줄에는 촌수를 계산해야 하는 서로 다른 두 사람의 번호가 주어진다. 그리고 셋째 줄에는 부모 자식들 간의 관계의 개수 m이 주어진다. 넷째 줄부터는 부모 자식간의 관계를 나타내는 두 번호 x,y가 각 줄에 나온다. 이때 앞에 나오는 번호 x는 뒤에 나오는 정수 y의 부모 번호를 나타낸다. 각 사람의 부모는 최대 한 명만 주어진다.

 

[코드]

import java.util.*;

public class BaekJoon_2644 {
	static int n,m,start,end,result=-1;
	static boolean[] visited;
	static ArrayList<ArrayList<Integer>> graph=new ArrayList<ArrayList<Integer>>();
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		visited=new boolean[n+1];
		
		for(int i=0;i<=n;i++)
			graph.add(new ArrayList<Integer>());
		
		start=sc.nextInt();
		end=sc.nextInt();
		m=sc.nextInt();
		
		for(int i=0;i<m;i++) {
			int a=sc.nextInt();
			int b=sc.nextInt();
			
			// 양방향
			graph.get(a).add(b);
			graph.get(b).add(a);
		}
		
		dfs(start, end, 0);
		System.out.println(result);
	}
	
	/*
	 * dfs 함수의 매개변수로 촌수를 세는 count가 있어야 한다.
	 * 그렇지 않고 전역변수로 선언한 변수를 증가시키면서 촌수를 count하게 되면
	 * 시작 노드로부터 end 노드까지 도달하는 과정에서 탐색한 모든 노드의 개수를 세게 된다.
	 *  
	 * 알고자하는 것은 start 노드에서 end 노드로 가는 길에 들르는 노드의 개수이기 때문에
	 * 조건을 만족할 때 전역변수에 count를 덮어쓰기 해야한다.
	 */
	public static void dfs(int start, int end, int count) {
		// end 노드에 도착했다면 촌수 덮어쓰기
		if(start==end) {
			result=count;
			return;
		}
		
		visited[start]=true; // 방문처리
		// 시작 번호로부터 연결되어 있는 노드 확인
		for(int i=0;i<graph.get(start).size();i++) {
			int next=graph.get(start).get(i);
			// 방문하지 않았던 노드라면 촌수를 +1하고, 해당 노드를 시작으로 재탐색한다. 
			if(!visited[next]) {
				dfs(next,end,count+1);
			}
		}
	}
}

 

[고찰]

 이번 문제는 촌수 관계를 그래프로 보고 시작 노드와 연결된 노드들을 탐색하며 거슬러 올라가 도착 노드를 찾아야하는 문제로 파악하여 DFS 알고리즘을 사용하여 해결하였다. 푸는 과정에서 두 가지의 실수가 있었다.

 첫 번째는 연결 정보를 입력받을 때 양방향 그래프인 점을 놓친 것이었다. 이렇게 되면 시작 노드로부터 위로 거슬러 올라갈 수 없기 때문에 양쪽의 노드를 모두 연결시켜주어야 한다. 두 번째는 촌수를 세는 변수를 함수의 매개변수가 아닌 전역변수를 사용한 점이다. 전역변수를 사용하게 되면 시작 노드로부터 끝 노드를 찾아가면서 탐색한 모든 노드의 개수를 count하게 된다. 따라서 함수의 매개변수로 촌수를 count하는 변수를 저장했다가 조건에 맞는 길을 탐색했을 때 결과를 덮어쓰는 방식으로 해결해야 한다.