#1. 문제
#2. 풀이
1. 벨만-포드 알고리즘
벨만-포드 알고리즘은 '음의 가중치'를 포함하는 그래프에서 "단일-출발" 혹은 "단일-쌍" 최단 경로 알고리즘을 찾는 간선 중심의 알고리즘입니다. 벨만 포드 알고리즘은 최단 경로 값을 찾는 값과 더불어 그래프 내 순환 경로에 존재하는 가중치의 합이 음수인 "음수 사이클"을 탐지하는 보조적인 작업을 병행합니다. 벨만-포드 알고리즘의 주요 포인트는 N-1번 간선 목록을 순회하며, 최단 경로 값을 업데이트한 후, 추가적으로 한번 더 간선 목록을 순회하며 최단 경로 값의 갱신 여부를 확인하여, 기존의 최단 경로 값이 다시 경신될 경우 그래프 내 음수 사이클 여부가 존재하는 것으로 간주합니다.
2. 웜홀은 '음수 가중치'를 갖는 간선, 도로는 '양수 가중치'를 갖는 간선!
- 간선 목록을 구성합니다.
- 벨만-포드 알고리즘을 통해 N-1번 간선 목록을 순회하며 최단 경로 값을 갱신합니다.
- 마지막 한 번의 간선 목록 순회를 통해 최단 경로 값 경신 여부를 체크하고, 해당 값이 경신될 경우 음수 사이클 여부를 확신하고 "NO"를 출력합니다!
#3. 코드
#include <iostream>
#include <string>
#include <vector>
#define MAX 30'000'000
using namespace std;
int n, m, w;
struct edge {
int s, e, t;
};
// 벨만-포드 알고리즘, 시작 정점은 무작위로 임의의 정점으로 설정해도 문제가 없습니다.
bool time_travel(int n, vector<edge> edges) {
vector<int> dist(n + 1, MAX);
int s, e, t;
dist[1] = 0;
for (int i = 1; i < n; i++) {
for (int j = 0; j < edges.size(); j++) {
s = edges[j].s;
e = edges[j].e;
t = edges[j].t;
if (dist[e] > dist[s] + t) {
dist[e] = dist[s] + t;
}
}
}
for (int j = 0; j < edges.size(); j++) {
s = edges[j].s;
e = edges[j].e;
t = edges[j].t;
if (dist[e] > dist[s] + t) {
return true;
}
}
return false;
}
int main()
{
cin.tie(NULL); cout.tie(NULL); ios_base::sync_with_stdio(false);
int TC;
cin >> TC;
int s, e, t;
while (TC > 0) {
cin >> n >> m >> w;
vector<edge> edges;
for (int i = 0; i < m; i++) {
cin >> s >> e >> t;
edges.push_back({ s,e,t });
edges.push_back({ e,s,t });
}
for (int i = 0; i < w; i++) {
cin >> s >> e >> t;
edges.push_back({ s,e,-t });
}
if (time_travel(n, edges)) cout << "YES\n";
else cout << "NO\n";
TC--;
}
return 0;
}
'문제 풀이 > BOJ 문제 풀이' 카테고리의 다른 글
[BOJ알고리즘, C++]#1766_문제집, 위상 정렬, 그래프 (0) | 2024.02.20 |
---|---|
[BOJ알고리즘, C++]#11657_타임 머신, 길 찾기, 최단 경로 알고리즘, 벨만-포드, 음수 가중치, 음수 사이클 (1) | 2024.02.06 |
[BOJ알고리즘, C++]#1068_트리, 그래프 탐색, 완전 탐색, 깊이 우선 탐색, DFS (0) | 2024.02.06 |
[BOJ알고리즘, C++]#11728_배열 합치기, 정렬, 병합 정렬 (0) | 2024.02.06 |
[BOJ알고리즘, C++]#2470_두 용액, 정렬, 퀵 정렬, 투 포인터 (1) | 2024.02.05 |