플로이드

2025. 8. 8. 16:34·알고리즘(코딩테스트)

1. 플로이드 알고리즘


모든 정점 쌍 사이의 최단 거리를 구하는 알고리즘

  • 방향 그래프나 무방향 그래프 모두 상관없음
  • 간선이 음수여도 동작함, 단 음수 사이클은 없어야 함
  • 시간 복잡도는 O(V^3)

왜 쓸까?

  • 예를 들어 정점이 100개 정도일 때 쓸만함 -> 코드가 쉬우니까
  • 모든 정점에 대한 거리를 알고 싶을 때 
  • 경유지를 고려해야 할 때 (다익스트라 같은 경우는 A->Z 까지의 최단 거리만 구하기 때문)
  • 또한 음수 가중치가 있는 경우..

 

2. 동작 방식


  • 먼저 테이블을 만들어 두고, 각 정점에서 인접한 정점까지의 거리만 업데이트하여 최단 거리 테이블을 만든다.

  • 지금까지 적어둔 값은 어떠한 정점을 거치지 않았을 때의 모습이다. 이제부터는 특정 정점을 거쳐가면서 더 짧은 경로가 있다면 업데이트 해주면 된다.
  • 아래 모습은 정점 1은 거쳐가는 경우 업데이트된 최단 거리 테이블의 모습이다

  • 위에서 한 방식을 모든 정점을 다 돌면서 수행하면 된다.
  • 코드로 생각해보면 업데이트 하는 부분에 있어서는 dp 방식과 유사한 비교를 하게 되는데, s에서 t로 가는동안 n을 지난다고 했을때 아래와 같은 코드를 통해 업데이트 하게 된다.
DP[s][t] = min(DP[s][t], DP[s][n] + DP[n][t]);

 

  • 모든 정점에 대해서 V 단계에 걸쳐서 갱신이 이루어지고, 각 단계마다 V^2개의 DP 값을 비교하기 때문에 시간 복잡도는 O(V^3) 이 된다.

 

3. 코드


주의점

  • 두 거리 덧셈에 있어서 int overflow 방지를 위해서 INF값 설정하기
  • 플로이드는 대충 정점 1000개까지는 해볼만 하다...
  • 비교하는 부분에서 min 함수를 쓰기보다 if문으로 체크하는 방식으로 바꾸면 좀 더 효율적이다
    • 이유는 대입을 매번 하는 것을 막을 수 있기 때문이다.
  • boj 11404 풀이
#include <iostream>
#include <climits>
using namespace std;

int n, m;
int arr[102][102];
const int INF = 0x3f3f3f3f;

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

	cin >> n;
	cin >> m;
	
	for (int i = 1; i <= n; ++i)
		fill(arr[i], arr[i] + 1 + n, INF);

	for (int i = 1; i <= n; ++i)
	{
		arr[i][i] = 0;
	}

	for (int i = 0; i < m; ++i)
	{
		int a, b, c;
		cin >> a >> b >> c;
		arr[a][b] = min(arr[a][b], c);
	}

	for (int i = 1; i <= n; ++i)
	{
		for (int j = 1; j <= n; ++j)
		{
			for (int k = 1; k <= n; ++k)
			{
				arr[j][k] = min(arr[j][k], arr[j][i] + arr[i][k]);
			}
		}
	}

	for (int i = 1; i <= n; ++i)
	{
		for (int j = 1; j <= n; ++j)
		{
			if (arr[i][j] == INF)
				cout << "0 ";
			else
				cout << arr[i][j] << " ";
		}
		cout << "\n";
	}
}

 

  • 추가) 사이클 구하기 (boj 1956)
#include <iostream>
using namespace std;

int board[402][402];
const int INF = 0x3f3f3f3f;
int v, e;
int answer = INF;

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

	cin >> v >> e;
	for (int i = 1; i <= v; ++i)
		fill(board[i] + 1, board[i] + 1 + v, INF);

	for (int i = 1; i <= v; ++i)
		board[i][i] = 0;

	for (int i = 0; i < e; ++i)
	{
		int a, b, c;
		cin >> a >> b >> c;
		board[a][b] = c;
	}

	for (int i = 1; i <= v; ++i)
	{
		for (int j = 1; j <= v; ++j)
		{
			for (int k = 1; k <= v; ++k)
			{
				board[j][k] = min(board[j][k], board[j][i] + board[i][k]);
			}
		}
	}

	//사이클 계산
	for (int i = 1; i <= v; ++i)
	{
		for (int j = i + 1; j <= v; ++j)
		{
			answer = min(answer, board[i][j] + board[j][i]);
		}
	}

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

'알고리즘(코딩테스트)' 카테고리의 다른 글

트라이  (0) 2025.09.08
위상정렬  (0) 2025.09.07
문자열 관련  (0) 2025.05.20
알고리즘 수업 최종 정리  (0) 2025.04.28
MST  (0) 2025.04.25
'알고리즘(코딩테스트)' 카테고리의 다른 글
  • 트라이
  • 위상정렬
  • 문자열 관련
  • 알고리즘 수업 최종 정리
gbleem
gbleem
gbleem 님의 블로그 입니다.
  • gbleem
    gbleem 님의 블로그
    gbleem
  • 전체
    오늘
    어제
    • 분류 전체보기 (189)
      • Unreal Engine (73)
      • C++ (19)
      • 알고리즘(코딩테스트) (32)
      • TIL (60)
      • CS (4)
      • 툴 (1)
  • 블로그 메뉴

    • 홈
    • 카테고리
  • 링크

    • 과제용 깃허브
    • 깃허브
    • velog
  • 공지사항

  • 인기 글

  • 태그

    템플릿
    blend pose
    map을 vector로 복사
    gamestate
    매크로 지정자
    C++
    enhanced input system
    character animation
    addonscreendebugmessage
    const
    DP
    cin함수
    motion matching
    상속
    additive animation
    싱글턴
    BFS
    Vector
    actor 클래스
    applydamage
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
gbleem
플로이드
상단으로

티스토리툴바