문제 링크


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

 

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

 

접근 방법


(1) 음수의 가중치가 존재하는 최단 거리 탐색 문제이므로 벨만-포드 알고리즘을 사용하면 된다.

 

(2) 문제에서 요구하는 출력

    1. 사이클의 가중치 합이 음수인 경우

    2. 버스가 도착지에 도달할 수 없는 경우

    3. 문제 없이 버스가 도착지에 도착한 경우

 

(3) (2)에서 요구한 조건을 만족하는 경우

   1. 벨만 포드 알고리즘의 핵심은 3중 for문의 가장 바깥 쪽 for문에서 i == N인 순간 갱신이 일어난다면 말할 것도 없         이 사이클의 가중치 합이 음수인 경우이다.

   2.  dist[j] == INF라면 단 한번도 j번째 지점이 갱신이 일어나지 않았다는 것이다. 즉 j번째 지점에 도착할 수 없다라는         말이 된다. 

   3. 만약 1번 조건에서 걸리게 되면 함수가 return이 되므로 1, 2의 조건에 모두 걸리지 않는다면 버스가 문제 없이

      도착하였다는 뜻이 된다.

 

(4) 주의할 점

 문제에서 주어지는 변수의 범위는 다음과 같다.

 

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

 

 최악의 경우에서 생각해본다면 1번부터 500번 노드까지 거쳐갈 수 있는 최대 노드의 갯수는 499개이고 가중치 C의 최댓값이 10000이므로 499*10000 이므로 INF는 4990000 이상은 잡아줘야 한다.

 

만약 모든 C가 -10000이면 어떨까? 

for (int i = 1; i <= N; i++) { 
	for (int from = 1; from <= N; from++) {
		for (int j = 0; j < graph[from].size(); j++) {
				//연산 
		}
	}
}

 graph[from].size()가 10 이상 이면 500*500*10*(-10000) = -2,500,000,000 즉 int의 범위를 벗어나 overflow가 발생한다.

그래서 dist는 long long으로 사용해야 적절한 답을 얻을 수 있다.

 

소스 코드


#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#define INF 0xFFFFFFF

using namespace std;

vector <pair<int, int>> graph[502];
long long dist[502];
int N, M;

void solve() {

	dist[1] = 0;
	bool updated = false;

	for (int i = 1; i <= N; i++) { 
		updated = false;
		for (int from = 1; from <= N; from++) {
			if (dist[from] == INF) 
				continue;
			for (int j = 0; j < graph[from].size(); j++) {
				int to = graph[from][j].first; 
				int cost = graph[from][j].second;
				if (dist[to] > dist[from] + cost) {
					dist[to] = dist[from] + cost;
					updated = true;
				}
			}
		}
		if (i == N) {
			if (updated == true) { // 1.사이클의 가중치 합이 음수인 경우
				cout << -1 << "\n"; 
				return;
			}
		}
	}
	for (int j = 2; j <= N; j++) {
		if (dist[j] == INF)   // 2. 버스가 도달할 수 없는 경우
			cout << -1 << "\n";
		else 		    // 3. 버스가 잘 도착한 경우
			cout << dist[j] << "\n"; 
	}
}

int main() {

	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	cin >> N >> M;
	for (int i = 0; i < 502; i++) 
		dist[i] = INF;
	
	for (int i = 0; i < M; i++) {
		int s, e, w;
		cin >> s >> e >> w;
		graph[s].push_back({ e,w });
	}
	solve();
}

 

개발 환경 : VS2019

질문, 지적 환영합니다!

'알고리즘 > 백준' 카테고리의 다른 글

[C++] 백준 2193 이친수  (0) 2020.09.04
[C++] 백준 12100 2048(Easy)  (0) 2020.08.10
[C++] 백준 1786 찾기 (KMP 알고리즘)  (0) 2020.06.29
[C++] 백준 1949 우수 마을  (0) 2020.06.12
[C++] 백준 2580 스도쿠  (0) 2020.06.10

+ Recent posts