거의 알고리즘 일기장

백준 1956번 _ 운동 본문

알고리즘 문제풀이

백준 1956번 _ 운동

건우권 2020. 4. 3. 22:04

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

 

1956번: 운동

첫째 줄에 V와 E가 빈칸을 사이에 두고 주어진다. (2<=V<=400, 0<=E<=V*(V-1)) 다음 E개의 줄에는 각각 세 개의 정수 a, b, c가 주어진다. a번 마을에서 b번 마을로 가는 거리가 c인 도로가 있다는 의미이다. (a->b임에 주의) 거리는 10,000 이하의 자연수이다.

www.acmicpc.net

 

1. 풀이 방법

V : 정점, E : 간선

 

1) 구하려는 것 : 모든 사이클에서의 최단거리 ( ex) 1 -> 2 ->1 가능 )

2) 구하기 위해 필요한 도구 : 정점에서 다른 정점까지의 최단거리

3) 모든 정점에서의 최단거리를 구할때는 -> 플로이드 와샬 알고리즘 ( V^3 )

4) 구한 이차배열을 순회하며 갔다올때 가장 적은 경로를 가지는 값 출력 ( V*( V - 1 ) ) 

 


 

2. 코드

 

#include <iostream>
#include <algorithm>
#include <vector>

#define INF 987654321

using namespace std;

int floyed[402][402];
int v, e;
//이어진노드, 거리
vector<vector<pair<int,int>>> edge;

int main()
{
	cin >> v >> e;
	edge.resize(v + 2);
	//folyed init
	for(int i =1; i<=v; i++)
		for (int j = 1; j <= v; j++)
		{
			if (i == j)
				continue;
			floyed[i][j] = INF;
		}

	//input
	int a, b, c;
	for (int i = 0; i < e; i++)
	{
		cin >> a >> b >> c;
		edge[a].push_back({ b, c });
		floyed[a][b] = min(floyed[a][b], c);
	}

	//foyed ㄱㄱ
	for(int mid = 1; mid<=v; mid++)
		for (int start = 1; start <= v; start++)
		{
			if (start == mid)
				continue;
			for (int end = 1; end <= v; end++)
			{
				//시작점과 끝점이 같거나, 중간점과 끝점이 같을때
				if (start == end || end == mid)
					continue;

				int comp = floyed[start][mid] + floyed[mid][end];
				floyed[start][end] = min(floyed[start][end], comp);
			}
		}

	//최소 사이클 찾기
	int answer = INF;
	for(int i=1; i<=v; i++)
		for (int j = i + 1; j <= v; j++)
		{
			answer = min(floyed[i][j] + floyed[j][i], answer);
		}

	if (answer >= INF)
		cout << -1;
	else
		cout << answer;

	return 0;
}

 


 

3. 후기

 

플로이드 와샬 알고리즘만 숙지하고 있다면 쉬운 문제였다.

반응형
Comments