투로드
Coder ToLoad
투로드
전체 방문자
오늘
어제

블로그 메뉴

  • 홈
  • 알고리즘
  • CS
  • GITHUB
  • 태그
  • 분류 전체보기 (69)
    • Toy Project (0)
      • EternalSNS (0)
    • Algorithm (46)
      • BaekJoon (38)
      • Programmers (7)
      • Code Tree (1)
    • Computer Science (13)
      • JAVA (7)
      • DataBase (4)
    • Backend (7)
      • Spring (2)
      • JPA (2)
      • Django (3)
    • Mobile (2)
      • Android (2)
    • Unity (1)

인기 글

최근 글

hELLO · Designed By 정상우.
투로드

Coder ToLoad

Algorithm/BaekJoon

[JAVA] 백준 11657 : 타임머신

2021. 5. 4. 17:08
문제
 

11657번: 타임머신

첫째 줄에 도시의 개수 N (1 ≤ N ≤ 500), 버스 노선의 개수 M (1 ≤ M ≤ 6,000)이 주어진다. 둘째 줄부터 M개의 줄에는 버스 노선의 정보 A, B, C (1 ≤ A, B ≤ N, -10,000 ≤ C ≤ 10,000)가 주어진다. 

www.acmicpc.net

해결 방법

 

벨만-포드 알고리즘을 사용해야 하는 문제이다.

한 정점에서 다른 모든 정점의 최단 경로를 탐색해야 하는데 Cost가 음인 경우 사용 가능하다.

 

최단 경로를 나타내는 배열을 최댓값으로 초기화 해준 다음 배열을 사용해서 탐색을 진행한다.

정점의 수 - 1 만큼 반복문을 통해 최단 경로를 탐색해주고, 

한 번 더 탐색하였을 때 또 최단 경로가 바뀐다고 하면 음의 사이클이 존재한다는 뜻이다.

 

여기서 말하는 음의 사이클이란 계속해서 최단 경로가 작아지는

즉, 1 -> 2 까지는 3만큼의 Cost로 이동할 수 있는데 2 -> 1로 올 때는 -4 만큼의 Cost로 이동이 가능하다.

이러한 경우 계속해서 최단경로가 줄어들게 되는데  이 같은 경우 음의 사이클이 존재한다고 말할 수 있다.

 

탐색이 모두 끝난 후 음의 사이클이 있다면 -1, 아니면 최단 경로를 출력하는데 최단 경로가 최댓값이면 그 정점은 탐색을 할 수 없었다는 뜻이므로 -1을 출력해준다.

 

코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {
	static ArrayList<Node> list[];
	static long dp[];
	static int N;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        
        list = new ArrayList[N + 1];
        dp = new long[N + 1];
        for (int i = 1; i <= N; i++) {
        	list[i] = new ArrayList<>();
        	dp[i] = Integer.MAX_VALUE;
        }
        
        for (int i = 0; i < M; i++) {
        	st = new StringTokenizer(br.readLine(), " ");
        	int start = Integer.parseInt(st.nextToken());
        	int end = Integer.parseInt(st.nextToken());
        	int cost = Integer.parseInt(st.nextToken());
        	
        	// 단방향으로 추가
        	list[start].add(new Node(end, cost));
        }
        
        
        StringBuilder sb = new StringBuilder();
        if(bellman()) {
        	for (int i = 2; i <= N; i++) {
        		if (dp[i] == Integer.MAX_VALUE) {
        			// 방문할 수 없었다는 뜻
        			sb.append(-1 + "\n");
        		} else {
        			sb.append(dp[i] + "\n");
        		}
        	}
        } else {
        	// 음의 사이클이 있는 경우
        	sb.append("-1");
        }
        System.out.println(sb);
    }
    
    static boolean bellman() {
    	dp[1] = 0;
    	
    	// 정점의 수 - 1 만큼 반복문을 돌림
    	for (int i = 1; i < N; i++) {
    		
    		// 1에서 출발해서 방문가능한 곳 탐색
    		for (int j = 1; j <= N; j++) {
    			for (Node node : list[j]) {
    				// 아직 해당 지점까지는 도착하지 못했으므로 탐색할 필요 없음.
    				if (dp[j] == Integer.MAX_VALUE) break;
    				
    				if (dp[node.next] > dp[j] + node.cost) {
    					dp[node.next] = dp[j] + node.cost;
    				}
    			}
    		}
    	}
    	
    	// 한번 더 탐색해서 또 값이 바뀌면 음의 사이클이 있다는 뜻
    	for (int i = 1; i <= N; i++) {
    		for (Node node : list[i]) {
    			if (dp[i] == Integer.MAX_VALUE) break;
				if (dp[node.next] > dp[i] + node.cost) return false;
			}
    	}
    	return true;
    }
}

class Node {
	int next;
	int cost;
	
	Node (int next, int cost) {
		this.next = next;
		this.cost = cost;
	}
}

'Algorithm > BaekJoon' 카테고리의 다른 글

[JAVA] 백준 16946 : 벽 부수고 이동하기 4  (0) 2021.06.02
[JAVA] 백준 2151 : 거울 설치  (2) 2021.05.25
[JAVA] 백준 1240 : 노드사이의 거리  (0) 2021.04.23
[JAVA] 백준 8972 : 미친 아두이노  (0) 2021.04.21
[JAVA] 백준 11967 : 불켜기  (0) 2021.04.20
    'Algorithm/BaekJoon' 카테고리의 다른 글
    • [JAVA] 백준 16946 : 벽 부수고 이동하기 4
    • [JAVA] 백준 2151 : 거울 설치
    • [JAVA] 백준 1240 : 노드사이의 거리
    • [JAVA] 백준 8972 : 미친 아두이노
    투로드
    투로드
    훌륭한 프로그래머가 되어가는 과정을 담아보는 중입니다.

    티스토리툴바