득이공간

[백준 C++] 1865 웜홀 - 벨만포드 본문

PS/알고리즘 문제풀이

[백준 C++] 1865 웜홀 - 벨만포드

쟁득 2024. 2. 2. 11:32
 

1865번: 웜홀

첫 번째 줄에는 테스트케이스의 개수 TC(1 ≤ TC ≤ 5)가 주어진다. 그리고 두 번째 줄부터 TC개의 테스트케이스가 차례로 주어지는데 각 테스트케이스의 첫 번째 줄에는 지점의 수 N(1 ≤ N ≤ 500),

www.acmicpc.net

#include <iostream>
#include <climits>
#include <vector>
#include <queue>
using namespace std;

const long long& Infinite = LLONG_MAX;

vector<vector<int>> EdgeList;
vector<long long> Solution;
queue<int> SearchQueue;

bool BellmanFord(int N, int K)
{
	for (int i = 0; i < N; ++i)
	{
		int EdgeSize = EdgeList.size();
		for (int j = 0; j < EdgeSize; ++j)
		{
			int Start = EdgeList[j][0];
			if (Solution[Start] != Infinite)
			{
				SearchQueue.push(j);
			}
		}

		while (!SearchQueue.empty())
		{
			int Current = SearchQueue.front();
			SearchQueue.pop();

			int Start = EdgeList[Current][0];
			int End = EdgeList[Current][1];
			int Weight = EdgeList[Current][2];

			long long NewWeight = Solution[Start] + Weight;
			if (NewWeight < Solution[End])
			{
				Solution[End] = NewWeight;
			}
		}
	}

	// Determine Infinite Cycle
	int EdgeSize = EdgeList.size();
	for (int j = 0; j < EdgeSize; ++j)
	{
		int Start = EdgeList[j][0];
		if (Solution[Start] != Infinite)
		{
			SearchQueue.push(j);
		}
	}

	while (!SearchQueue.empty())
	{
		int Current = SearchQueue.front();
		SearchQueue.pop();

		int Start = EdgeList[Current][0];
		int End = EdgeList[Current][1];
		int Weight = EdgeList[Current][2];

		long long NewWeight = Solution[Start] + Weight;
		if (NewWeight < Solution[End])
		{
			return true;
		}
	}

	return false;
}

void Test()
{
	int N, M, W;
	cin >> N >> M >> W;

	EdgeList.clear();
	EdgeList.reserve(2 * M + W);
	for (int i = 0; i < 2 * M + W; ++i)
	{
		EdgeList.emplace_back(vector<int>(3, 0));
	}

	for (int i = 0; i < M; ++i)
	{
		int Start, End, Weight;
		cin >> Start >> End >> Weight;

		EdgeList[i][0] = Start - 1;
		EdgeList[i][1] = End - 1;
		EdgeList[i][2] = Weight;

		EdgeList[M + i][0] = End - 1;
		EdgeList[M + i][1] = Start - 1;
		EdgeList[M + i][2] = Weight;
	}

	for (int i = 0; i < W; ++i)
	{
		int Start, End, Weight;
		cin >> Start >> End >> Weight;

		EdgeList[2 * M + i][0] = Start - 1;
		EdgeList[2 * M + i][1] = End - 1;
		EdgeList[2 * M + i][2] = -1 * Weight;
	}

	Solution.clear();
	Solution.reserve(N);
	for (int i = 0; i < N; ++i)
	{
		Solution.emplace_back(0);
	}

	if (BellmanFord(N, 0))
	{
		cout << "YES\n";
	}
	else
	{
		cout << "NO\n";
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int TC;
	cin >> TC;
	for (int i = 0; i < TC; ++i)
	{
		Test();
	}
}

벨만-포드 알고리즘을 사용해서 풀었습니다.

 

주의할 점은 서로 연결된 노드의 집합이 여러개 존재할 수 있다는 것입니다. (모든 노드가 연결되어있지 않을 수 있다.)

따라서 특정 한 가지 노드를 시작점으로 두지 말고

모든 노드에서 출발 가능하도록

최단 거리 배열을 Inf가 아닌 0으로 초기화를 해주어야 합니다.