반응형
https://www.acmicpc.net/problem/1738
1738번: 골목길
첫째 줄에 골목길들이 교차하는 지점의 개수 n (2 ≤ n ≤ 100)과 골목길의 개수 m (1 ≤ m ≤ 20,000) 이 차례로 주어진다. 이어지는 m개의 행에 각각의 골목길을 나타내는 세 정수 u, v, w가 차례로
www.acmicpc.net
1. 문제설명
간선의 cost를 뺏기는 양으로 두면
금을 땅에서 주울 경우에는 마이너스
뺏길 경우는 플러스로 두게 되어 이동하는데 필요한 cost를 설정할 수 있다.
이후 벨만포드 알고리즘을 적용해서 풀면 된다.
단 이 문제의 경우 음의 사이클이 존재한다고 무조건 -1이 될 수 없다.
왜냐하면 음의 사이클이 존재해도 시작점에서 도착점까지 가는데 경유하지 않을 수 있기 때문이다
즉 음의사이클이 존재는 하나 따로 동떨어진 경우가 테스트케이스로 들어올 수도 있다.
그래서 음의사이클이 존재하고 음의사이클에서 도착점으로 가는지 판단해야한다.
또한 출발점 1에서 도착점 n까지 도달할 수 있는지 확인해야한다.
이를 위해 역방향 간선을 저장해두고 n으로부터 시작하여 BFS를 돌면
1과 음의 사이클에서 도착점까지 갈 수 있는지 확인할 수 있다.
2. 문제풀이코드 C++
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pi;
const long long INF = 1e18;
long long dist[101];
int pre[101];
int n, m;
vector<pi> adj[101];
vector<pi> rev_adj[101];
bool goal[101];
void check_goal() {
queue<int> Q;
Q.push(n);
goal[n] = 1;
while (!Q.empty()) {
int x = Q.front(); Q.pop();
for (auto &i : rev_adj[x]) {
int nx = i.first;
if (goal[nx] == 0) {
Q.push(nx);
goal[nx] = 1;
}
}
}
}
void print(int n) {
if (n == 0) return;
print(pre[n]);
cout << n << ' ';
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
adj[u].push_back({ v,-w });
rev_adj[v].push_back({ u,-w });
}
check_goal();
//시작점에서 도착점 가는 길이 없는 경우
if (goal[1] == 0) {
cout << -1 << '\n';
return 0;
}
fill(dist, dist + 101, INF);
dist[1] = 0;
for (int i = 0; i < n; i++) {
for (int j = 1; j <= n; j++) {
for (auto& a : adj[j]) {
int nx = a.first;
int d = a.second;
if (dist[j] != INF && dist[nx] > dist[j] + d) {
pre[nx] = j;
dist[nx] = dist[j] + d;
if ((i == n-1) && (goal[j])) {
cout << -1 << '\n';
return 0;
}
}
}
}
}
print(n);
return 0;
}
반응형
'Algorithm > problem' 카테고리의 다른 글
백준 2096번 내려가기 C++ (0) | 2022.04.03 |
---|---|
백준 1707번 : 이분 그래프 (0) | 2022.03.22 |
백준 11997번 : Load Balancing(Silver) - 누적합, 좌표 압축 C++ (0) | 2022.03.11 |
백준 7662번 : 이중 우선순위 큐 - priority queue & map (0) | 2022.03.10 |
백준 16139번 : 인간 - 컴퓨터 상호작용 - 구간 합 C++ (0) | 2022.03.10 |