1865번: 웜홀
첫 번째 줄에는 테스트케이스의 개수 TC(1 ≤ TC ≤ 5)가 주어진다. 그리고 두 번째 줄부터 TC개의 테스트케이스가 차례로 주어지는데 각 테스트케이스의 첫 번째 줄에는 지점의 수 N(1 ≤ N ≤ 500),
www.acmicpc.net
- 처음엔 플로이드-와샬 문제인 줄
- 문제 태그에 벨만-포드라고 되어 있는데, 풀어본 적 없어서 먼저 벨만포드를 공부하고 풀었다.
- 처음엔 거리 갱신 시 시작점이 INF 일 경우 갱신하지 않는 것으로 코드를 작성했다가, 계속 틀렸었다.
- 이는 특정 노드에서 시작할 경우 해당 노드가 다른 음의 순환이 있는 노드들과 단절돼있을 경우 반영이 안되기 때문이다.
- 사실 음의 순환이 존재하는지만 확인하기 위해서는 INF 비교나 INF 초기화가 필요 없다.
- 어차피 n-1 번 동안 최단거리로 업데이트 되고, 마지막 반복에서 갱신이 일어나는지만 확인하면 되기 때문.
#include <iostream>
#include <vector>
#define INF 100000000
using namespace std;
int TC;
int N, M, W;
bool bf() // 음의 싸이클 존재 여부 리턴
{
cin >> N >> M >> W;
vector<pair<pair<int,int>,int>> edges; // 입력받는 모든 엣지들 저장
int s, e, t;
for(int m = 0 ; m < M ; m++)
{
cin >> s >> e >> t;
edges.push_back({{s,e},t}); // 양방향으로 저장
edges.push_back({{e,s},t});
}
for(int w = 0 ; w < W ; w++)
{
cin >> s >> e >> t;
edges.push_back({{s,e},-t});
}
vector<int> dist(N+1, INF); // 거리 정보, 대충 초기화
dist[1] = 0; // 시작점은 아무데나 설정
for(int v = 0 ; v < N ; v++) // n-1 번 반복으로 최단거리 구하고, 마지막 1번으로 변화 유무 파악
{
for(int i = 0 ; i < edges.size() ; i++) // 모든 엣지를 보면서
{
int start = edges[i].first.first, end = edges[i].first.second;
if((dist[end] > dist[start] + edges[i].second)) // 거리 갱신되는 노드들 업데이트
{
if(v == N-1) return true; // 마지막 반복이었을 경우, 거리 갱신 시 음의 싸이클 존재
dist[end] = dist[start] + edges[i].second;
}
}
}
return false;
}
int main(void)
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> TC;
for(int tc = 0 ; tc < TC ; tc++)
{
if(bf()) cout << "YES" << endl; // 음의 싸이클이 존재할 경우에 따라 답 출력
else cout << "NO" << endl;
}
}
'PS > BOJ' 카테고리의 다른 글
[백준] 2096 : 내려가기 (0) | 2021.03.21 |
---|---|
[백준] 1967 : 트리의 지름 (0) | 2021.03.20 |
[백준] 3273 : 두 수의 합 (0) | 2021.03.16 |
[백준] 3055 : 탈출 (0) | 2021.03.14 |
[백준] 10452 : 피보나치 인버스 (0) | 2021.02.11 |