알고리즘/백준
[백준] 1738번 - 골목길
래울
2024. 7. 6. 23:29
문제
1738번 골목길: https://www.acmicpc.net/problem/1738
오랫만에 고통 좀 받은 문제, 얼른 풀고 SCC공부하려 했는데 시간 다 뺏김 ㅜㅜ
양 또는 음의 가중치를 가지는 그래프에서 사이클을 판별하고 경로 추적을 하는 문제 (그래프, 벨만-포드)
벨만 포드는 몰라서, SPFA로 품
풀이
1. 역방향 그래프를 생성해서 BFS를 돌려 해당 정점에서 N정점에 도달 가능한지 여부를 판단
만약 해당 정점이 N정점에 도달하지 않는 정점이라면 1에서 N정점간의 비용을 구할 때 고려하지 않아도 된다. (사이클이 존재하지만 정답을 출력하는 경우!)
2. SPFA 돌리기, SPFA 경로추적은 몰라서 그냥 다익스트라처럼 비슷하게 추적함
if(check[nxt.n] == 0) continue; 와 같이 1번의 경우 고려X
3. 스택으로 간선 출력
코드
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <cstring>
#include <cmath>
#include <unordered_map>
#include <string>
using namespace std;
int N, M;
int check[101];
int visitedCnt[101];
int visited[101];
struct Node {
int n, cost;
};
vector<Node> graph[101];
vector<Node> rev[101];
int answer[101];
vector<int> path[101];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int fg = 0;
cin >> N >> M;
for (int i = 0; i < M; ++i)
{
int a, b, c;
cin >> a >> b >> c;
if (a == b) fg = 1;
graph[a].push_back({ b, -c });
rev[b].push_back({ a, -c });
}
for (int i = 1; i <= N; ++i) answer[i] = 1987654321;
// 역방향으로 각 노드가 도착점에 도달 가능한지 검사
queue<int> q;
q.push(N);
check[N] = 1;
while (!q.empty())
{
int now = q.front();
q.pop();
for (int i = 0; i < rev[now].size(); ++i)
{
Node nxt = rev[now][i];
if (check[nxt.n]) continue;
check[nxt.n] = 1;
q.push(nxt.n);
}
}
if (check[1] == 0) {
//시작점이 도착점에 도달 불가한 경우
cout << -1;
return 0;
}
// SPFA
q.push(1);
answer[1] = 0;
visited[1] = 1;
while (!q.empty())
{
int now = q.front();
q.pop();
visitedCnt[now]++;
visited[now] = 0;
if (visitedCnt[now] >= N) {
cout << -1;
return 0;
}
for (int i = 0; i < graph[now].size(); ++i)
{
Node nxt = graph[now][i];
int nxtCost = answer[now] + nxt.cost;
if (check[nxt.n] == 0) continue;
if (nxtCost > answer[nxt.n]) continue;
else if (nxtCost == answer[nxt.n]) {
path[nxt.n].push_back(now);
}
else {
path[nxt.n].clear();
path[nxt.n].push_back(now);
answer[nxt.n] = nxtCost;
if (visited[nxt.n] == 0)
{
visited[nxt.n] = 1;
q.push(nxt.n);
}
}
}
}
stack<int> ans;
for (int i = N; i != 1; i = path[i][0]) {
ans.push(i);
}
cout << "1 ";
while (!ans.empty()) {
cout << ans.top() << " ";
ans.pop();
}
return 0;
}