[BOJ: 1005/ JAVA] ACM Craft

2025. 9. 12. 11:33·Algorithm/BOJ & SWEA
728x90

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

 

백준 1005번 문제 사진

1. 문제 요약

특정 건물을 가장 빨리 지을 때까지 걸리는 최소 시간을 알아내는 프로그램 

 

※ 주의할 점 

최소 시간을 알아내는 프로그램 이라지만, 동시에 건축을 해야하는 건물의 경우 
그 건물들이 모두 건축이 완성되어야 다음 건물을 건축할 수 있기 때문에 최소 시간을 그리 신경쓸 필요 없는 듯 하다. 

 


 

2. 알고리즘 (접근 방법) 

○ 위상 정렬 방식 (Queue) 

 

여기서 정점은 건축물을 말하는 것이며, 진입차수는 해당 건축물과 연결된 이전 건축물과의 간선이 몇개인지를 말하는 것이다. 

1005번 사진에서는 1, 2, 3, 4 건축물들이 모두 정점임을 의미하고, 1번 정점이 3번 정점과 연결되어 있고 이를 간선이라고 표한다. 
여기서 3번 정점으로 들어오는 진입차수는 1번과 연결된 간선 1개이다. 
또 다른 예로 4번 정점으로 들어오는 진입차수는

- 3번에서 들어오는 간선 1개

- 2번에서 들어오는 간선 1개

총 2개의 진입차수를 갖고 있다. 

 

1. 위상 정렬 방식으로 먼저 세팅을 해준다. 

  • 진입차수가 0인 모든 정점을 Queue 에 삽입
for(int v = 1; v < V+1; v++) {
    if(inDegree[v] == 0) { // 진입차수가 없다면 방문을 해볼까나 
        q.add(v);
    }
}

 

  • Queue 가 공백이 될 때까지 반복 수행 
while(!q.isEmpty()) {
	// ... 로직 
}
  • 반복문 내에서 Queue 안에 있는 원소를 꺼내 해당 노드에서 나가는 간선(즉, 진입차수)을 그래프에서 제거한다.
int curr = q.poll(); // 큐에 담긴 맨앞에꺼 꺼내기 
    List<Integer> list = adjList[curr]; 

    // curr 인접한 정점을 순회하면서 간선 제거
    for(int i = 0; i < list.size(); i++) {
        int next = list.get(i); // 2, 3

        // curr 과 인접한 정점의 진입차수를 하나씩 제거 해주기 
        inDegree[next]--;

        //...다음 로직 
}
  • 반복문 내에서 새롭게 진입차수가 0이 된 노드를 Queue 삽입한다.
if(inDegree[next] == 0) {
    q.add(next);
}

 

 

2. 반복문 내에서 인접한 정점을 건축하는 시간 (only 해당 정점의 건축시간) 과 해당 정점까지 오는데 걸린 건축시간과 비교하여 누적값을 넣어준다. 

 

↓ 예시 더보기 클릭 

더보기
더보기

현재 정점 (curr 변수에 담긴 값) 와 인접한 정점(list.get(i) 해서 나오는 next 변수에 담긴 값) 을 건축하는 시간과

그 인접한 정점까지 오는데 걸린 시간을 합한 것이 bt 이다.

예를 들자면,

현재 정점은 3번이며, 인접한 정점은 4번인 상황이다. 

4번 정점까지 오는데 있어서 1 → 3 → 4 순으로 왔다면 

- times[next] = 4번 정점을 짓는 건축시간 10초

- result[curr] = 3번 정점 건축물까지 짓는데 걸린 건축시간 110초 (10 + 100) 

총 120 초가 된다. 

result[next] 에 담긴 값은 현재 times[next] 에 담긴 값과 같기에 

- 10초 < 120초 비교하여 120 초가 resutl[next] 에 들어가게 되는 구조이다.

// 차수가 갱신된 건물을 짓는데 걸리는 시간 
int bt = times[next] + result[curr];
result[next] = Math.max(bt, result[next]);

 

 

3. 최종 코드 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class Main {
	 
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine()); 
		StringBuilder sb = new StringBuilder();
		for(int t = 0; t < T; t++) {
			
			StringTokenizer st = new StringTokenizer(br.readLine());
			int V = Integer.parseInt(st.nextToken()); // 건물 개수 (정점의 개수) 
			int E = Integer.parseInt(st.nextToken()); // 건설 순서 규칙 개수 (간선의 개수) 
			
			ArrayDeque<Integer> q = new ArrayDeque<>(); 
			int[] times = new int[V+1];  
			List<Integer>[] adjList= new ArrayList[V+1]; 
			int[] inDegree = new int[V+1];
			int[] result = new int[V+1];
			
			st = new StringTokenizer(br.readLine());
			for(int v = 1; v < V+1; v++) {
				int time = Integer.parseInt(st.nextToken());
				times[v] = time; 
				result[v] = time;  
				adjList[v] = new ArrayList<>();				  
			}
			
			for(int e = 0; e < E; e++) {
				st = new StringTokenizer(br.readLine());
				int from = Integer.parseInt(st.nextToken()); // 정점 1
				int to = Integer.parseInt(st.nextToken());   // 정점 2 (진입차수를 받는 정점) 
				
				adjList[from].add(to); 		// 유향 리스트 
				inDegree[to]++; 			// 진입차수 세팅 
			}
			
			// 건축해야할 번호 받기 
			int W = Integer.parseInt(br.readLine());
			
			for(int v = 1; v < V+1; v++) {
				if(inDegree[v] == 0) { // 진입차수가 0 인 정점을 큐에 추가
					q.add(v);
				}
			}
			
			// 큐가 공백이 될때까지 돌리기
			while(!q.isEmpty()) {
				int curr = q.poll(); // 큐에 담긴 정점 꺼내기
				List<Integer> list = adjList[curr];  // 해당 정점과 연결된 다음 정점들 리스트
				
	        	// curr 인접한 정점을 순회하기 
				for(int i = 0; i < list.size(); i++) {
					int next = list.get(i); 
					
                    // 인접한 정점의 진입차수 감소 시키기
					inDegree[next]--;
					
                    // 진입차수가 0이 되었다면, 큐에 담기 
					if(inDegree[next] == 0) {
						q.add(next);
					}
		         	// 차수가 갱신된 건물을 짓는데 걸리는 시간 
					int bt = times[next] + result[curr];
                    // 위에서 계산한 값과 기존에 가지고 있는 값 중 큰 값을 누적 값에 저장
					result[next] = Math.max(bt, result[next]);
				}
				
			}
            
            // 특정 건물 (W) 를 짓는데 걸리는 시간 출력 
			sb.append(result[W]).append("\n");
		}
		
		// 결과 출력
		System.out.println(sb);
	}

}

 

728x90

'Algorithm > BOJ & SWEA' 카테고리의 다른 글

[BOJ:1342 / JAVA] 행운의 문자열  (5) 2025.09.26
[BOJ: 7785/ JAVA] 회사에 있는 사람  (0) 2025.08.24
[SWEA:14510/JAVA] 나무 높이  (2) 2025.08.24
[백준 : JAVA] 1439. 뒤집기  (2) 2025.03.08
[백준:2903/Python] 중앙 이동 알고리즘  (0) 2023.11.02
'Algorithm/BOJ & SWEA' 카테고리의 다른 글
  • [BOJ:1342 / JAVA] 행운의 문자열
  • [BOJ: 7785/ JAVA] 회사에 있는 사람
  • [SWEA:14510/JAVA] 나무 높이
  • [백준 : JAVA] 1439. 뒤집기
is낫널
is낫널
  • is낫널
    아직은 NULL NULL 합니다
    is낫널
  • 전체
    오늘
    어제
    • 분류 전체보기 (52)
      • Computer Science (12)
        • 운영체제 (3)
        • Java (4)
        • Spring (0)
        • 네트워크 (2)
        • 자료구조 및 알고리즘 (0)
        • 데이터베이스 (1)
      • Algorithm (10)
        • BOJ & SWEA (8)
        • Programmers (0)
        • 이론 (2)
      • Project (7)
        • Team (3)
        • Personal & Toy (4)
      • 사회인 준비생 (22)
        • SSAFY (5)
        • 이직 (1)
        • TIL (14)
      • 무작정 따라해보기 (1)
        • 블로그 (1)
  • 블로그 메뉴

    • 홈
    • 글쓰기
    • 태그
    • 방명록
    • 블로그 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    개발자
    빈 라인
    파이썬
    transiant
    backend
    AWS
    it세계의 괴물들
    14510 나무 높이
    LAMBDA
    백준
    BOJ
    자바
    카카오톡API
    그림자 문제
    문자열
    개발공부
    CS지식
    코딩테스트
    백엔드
    딩코딩코
    비전공자
    Java
    인터럽트핸들러
    알고리즘
    CPU의 구성요소
    HTTP
    sw적성진단
    개발
    Roy Fielding
    백엔드 면접지식
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
is낫널
[BOJ: 1005/ JAVA] ACM Craft
상단으로

티스토리툴바