※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 1738번 문제인 골목길이다.
문제는 아래 링크를 확인하자.

https://www.acmicpc.net/problem/1738 

 

1738번: 골목길

첫째 줄에 골목길들이 교차하는 지점의 개수 n (2 ≤ n ≤ 100)과 골목길의 개수 m (1 ≤ m ≤ 20,000) 이 차례로 주어진다. 이어지는 m개의 행에 각각의 골목길을 나타내는 세 정수 u, v, w가 차례로

www.acmicpc.net

주어진 그래프에서 도착점으로 도착할 수 없거나 "무한히 돌면서 돈을 벌 수 있는, 출발점에서 들어올 수 있고 도착점으로 빠져나갈 수 있는 사이클"이 존재한다면 -1을, 그렇지 않다면 출발점에서 도착점까지 가는 최단경로를 출력하는 문제이다.

 

이를 판단하기 위해 Bellman-Ford 알고리즘을 이용하자.

 

사이클에서 도착점으로 이동할 수 있는가를 판단할 때, Bellman-Ford의 relaxation을 이용하여 구현하면 다음과 같은 노드 100개짜리 데이터를 뚫기 어렵게 된다. 주어진 사이클을 몇 바퀴 돌아야하는지를 생각해보자.

 

  • 1->2, 2->3, ..., 49->50의 -1000의 가중치를 가진 에지들
  • 50~99번 노드로 구성된 가중치가 1인 양의 사이클
  • 50->100의 -1000의 가중치를 가진 에지
  • 1->100의 1000의 가중치를 가진 에지

 

따라서, 사이클을 이루는 노드에서 DFS나 BFS 등의 그래프탐색을 통해 도착점으로 갈 수 있는지를 판단하는 것이 좋다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;

struct edge {
	int x, y;
	ll d;
	edge(int x, int y, ll d) {
		this->x = x, this->y = y, this->d = d;
	}
};

vector<int> G[101];
bool iscycle[101];
bool visited[101];
int parent[101];
ll dist[101];
vector<edge> edges;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	int N, M; cin >> N >> M;
	while (M--) {
		int x, y, w; cin >> x >> y >> w;
		edges.emplace_back(edge(x, y, -w));
		G[x].emplace_back(y);
	}

	visited[1] = 1;
	for (int i = 1; i < N; i++) {
		for (auto& e : edges) {
			if (visited[e.x]) {
				if (visited[e.y]) {
					if (dist[e.y] > dist[e.x] + e.d) {
						dist[e.y] = dist[e.x] + e.d;
						parent[e.y] = e.x;
					}
				}
				else {
					visited[e.y] = 1;
					dist[e.y] = dist[e.x] + e.d;
					parent[e.y] = e.x;
				}
			}
		}
	}

	for (auto& e : edges) {
		if (visited[e.x]) {
			if (visited[e.y]) {
				if (dist[e.y] > dist[e.x] + e.d) iscycle[e.x] = 1;
			}
		}
	}

	queue<int> que;
	for (int i = 1; i <= N; i++) if (iscycle[i]) que.push(i);
	while (!que.empty()) {
		int current = que.front(); que.pop();
		for (auto node : G[current]) {
			if (iscycle[node]) continue;
			iscycle[node] = 1;
			que.push(node);
		}
	}

	if (iscycle[N] || !visited[N]) cout << -1;
	else {
		vector<int> stk;
		while (N > 1) {
			stk.emplace_back(N);
			N = parent[N];
		}
		cout << 1;
		while (!stk.empty()) {
			cout << ' ' << stk.back();
			stk.pop_back();
		}
	}
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 13317 // C++] 한 번 남았다  (0) 2021.12.15
[BOJ 3860 // C++] 할로윈 묘지  (0) 2021.12.14
[BOJ 7577 // C++] 탐사  (0) 2021.12.12
[BOJ 7634 // C++] Guessing Game  (0) 2021.12.11
[BOJ 7040 // C++] 밥 먹기  (0) 2021.12.10

+ Recent posts