풀이과정
이 문제는 벨만 포드의 대표적인 기본 문제이다.
그 이유는 타임머신으로 시간을 되돌아가는 경우가 있으므로 가중치가 음수가 될 수 있기 때문이다. 가중치에 음수가 있다면 다익스트라가 아닌, 벨만 포드 알고리즘을 생각해야 한다.
문제에 있는 '시간을 무한히 오래전으로 되돌릴 수 있다면'이라는 말은 '음의 사이클이 존재한다면' 뜻이다. N번째에도 변하는 값이 있다면 cycle를 true로 바꿔줘 음의 사이클이 존재한다는 것을 표시해준다.
=> dist를 long long으로 구현하는 이유?
N = 500이고, M = 6000일 때, 6000개의 간선이
1 -> 2 로 -10000 만큼의 비용이 든다.
2 -> 1 로 -10000 만큼의 비용이 든다.
위의 경우는 음의 사이클이 발생함에도, int형의 범위를 넘어가므로 음의 사이클이 발생하지 않는다. 따라서 long long으로 구현해야 한다.
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
#define INF 2100000000
int N, M, x, y, z;
long long dist[501];
bool cycle;
vector <pair <int, int>> edge[501];
void bellman_ford() {
fill(dist, dist + N + 1, INF); // 변경하려는 원소의 범위 시작주소, 변경하려는 원소 개수, 변경 값
dist[1] = 0;
for (int k = 1; k <= N; k++) {
for (int i = 1; i <= N; i++) {
for (int j = 0; j < edge[i].size(); j++) {
int next = edge[i][j].first;
int nextcost = edge[i][j].second;
if (dist[i] != INF && dist[next] > dist[i] + nextcost) {
dist[next] = dist[i] + nextcost;
if (k == N) cycle = true;
}
}
}
}
if (cycle) cout << -1;
else {
for (int i = 2; i <= N; i++)
// dist[i] = INF 경우는 해당 도시로 가는 경로가 없는 것
cout << (dist[i] != INF ? dist[i] : -1) << "\n";
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> N >> M;
for (int i = 0; i < M; i++) {
cin >> x >> y >> z;
edge[x].push_back({ y, z });
}
bellman_ford();
}
'🍞 Problem Solving > Baekjoon' 카테고리의 다른 글
[백준] 1976 여행 가자 c++ (0) | 2022.09.05 |
---|---|
[백준] 1717 집합의 표현 c++ (0) | 2022.09.05 |
[백준] 1956 운동 c++ (0) | 2022.09.05 |
[백준] 1719 택배 c++ (0) | 2022.09.05 |
[백준] 1613 역사 c++ (0) | 2022.09.05 |