허스크 2021. 5. 28. 10:21
반응형
 

11404번: 플로이드

첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가

www.acmicpc.net

#include <iostream>
#include <algorithm>
using namespace std;

int n, m, from, to, cost;
int bus[101][101];

// 플로이드-와샬 알고리즘
// 1~2로 가는데 만약 3을 거쳐가는게 더 빠르다고 하면 3을 거쳐가는 비용으로 업데이트
void F(){
    for(int v = 1; v <= n; v++){
        for(int f = 1; f <= n; f++){
            if(!bus[f][v])
                continue;
            for(int t = 1; t <= n; t++){
                if(!bus[v][t] || f == t)
                    continue;
                
                if(bus[f][t] > bus[f][v] + bus[v][t] || !bus[f][t])
                    bus[f][t] = bus[f][v] + bus[v][t];
            }
        }
    }
}

int main(){
    scanf("%d", &n);
    scanf("%d", &m);
    for(int i = 0; i < m; i++){
        scanf("%d %d %d", &from, &to, &cost);

        if(!bus[from][to])
            bus[from][to] = cost;
        else
            bus[from][to] = min(bus[from][to], cost);
    }

    F();

    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            printf("%d ", bus[i][j]);
        }
        printf("\n");
    }
}

 플로이드-와샬의 간단한 이론만 알 수 있다면 풀 수 있는 문제입니다. '출발-도착' 보다 '출발-경유지-도착'이 더 빠른경우 찾아낼 수 있는 알고리즘으로 시간복잡도가 n^3이다 보니 n이 크지 않은 문제들, 모든 출발지-도착지 쌍을 구하는 경우에 사용되게 됩니다.

  풀이를 하면서 조금 헷갈린 부분은

void F(){
    for(int v = 1; v <= n; v++){
        for(int f = 1; f <= n; f++){
            if(!bus[f][v])
                continue;
            for(int t = 1; t <= n; t++){
                if(!bus[v][t] || f == t)
                    continue;
                
                if(bus[f][t] > bus[f][v] + bus[v][t] || !bus[f][t])
                    bus[f][t] = bus[f][v] + bus[v][t];
            }
        }
    }
}

 위 플로이드 함수에서 제일 안쪽 포문의 두번째 if에 있는 !bus[f][t] 였습니다. 처음에는 위에 넣어야 하는게 아닌가 했지만 생각해보니 아래 if에 둬야 출발지-도착지를 전부 구할 수 있게 됩니다.

반응형