본문 바로가기

Algorithm/H. Trees & Graphs

118. Shortest Path Faster Algorithm

Shortest Path Faster Algorithm(SPFA)은 벨만-포드 알고리즘을 약간 변형한 것으로 간선을 확인할 때 $d_v$의 값이 변하지 않았을 경우 그 정점과 인접한 정점을 다음 차례에 바로 확인할 필요가 없다는 성질을 이용한다. 작동 방식은 다음과 같다.

    1. 시작 정점은 $k$, 정점 $k$로부터 정점 $i$까지의 최단 거리를 $d_i$라고 한다.

    2. 정점 $x$에서 정점 $y$로 가는 가중치 $z$인 간선이 존재할 때 $w(x, y) = z$라고 한다.

    3. $d_k$는 $0$, 나머지 $d_i$는 모두 $\infty$로 초기화한다.

    4. 빈 큐에 정점 $k$를 추가한다.

    5. 큐에서 정점 하나를 뺀다. 이 정점을 $u$라고 하자.

    6. $u$에서 나가는 간선이 존재하는 각각의 정점 $v$에 대해 $d_u + w(u, v) < d_v$라면 $d_v$를 $d_u + w(u, v)$로 바꾸고 큐에 $v$가 존재하지 않을 경우 큐에 $v$를 추가한다.

    7. 큐가 빈 경우 실행을 종료한다. 그렇지 않은 경우 5번으로 돌아간다.

 

어떻게 보면 다익스트라 알고리즘과도 유사하다. 다만 다익스트라 알고리즘에서는 우선순위 큐를, SPFA에서는 큐를 사용한다는 점과 SPFA에서는 큐에 포함된 원소의 개수가 항상 정점의 수 $n$을 넘지 않는다는 점 등이 서로 다르다. SPFA 알고리즘의 시간복잡도는 최악의 경우 $O(nm)$이지만 실제로는 더 빠른 경우가 많고, 평균 시간복잡도가 $O(m)$임이 알려져 있다.

 

구현은 다음과 같다. $w$ 배열은 큐에 각각의 정점이 존재하는지를 체크한다.

#import<bits/stdc++.h>
using namespace std;
int d[1005], w[1005];
vector<pair<int, int>>e[1005];
queue<int>Q;
int main()
{
    int k, m, n, x, y, z;
    cin >> n >> m >> k;
    for(int i = 1; i <= m; i++)
    {
        cin >> x >> y >> z;
        e[x].push_back({y, z});
    }
    fill(d + 1, d + n + 1, 1 << 30);
    d[k] = 0;
    for(Q.push(k); Q.size(); Q.pop())
    {
        int u = Q.front();
        w[u] = 0;
        for(auto &p: e[u])
        {
            int v = p.first;
            if(d[u] + p.second < d[v])
            {
                d[v] = d[u] + p.second;
                if(!w[v])
                {
                    Q.push(v);
                    w[v] = 1;
                }
            }
        }
    }
}

그래프에 시작 정점에서 도달할 수 있는 음수 사이클이 존재할 경우 실행이 안 끝날 수도 있으므로 주의해야 한다. 다만 시작 정점에서 도달할 수 있는 음수 사이클을 감지하는 것은 가능한데, 한 정점이 큐에 $n$번 이상 들어가는 등의 상황이 발생할 경우 음수 사이클이 존재한다고 할 수 있다.

 

SPFA는 나중에 MCMF를 다룰 때 다시 등장하며, 실제로도 벨만-포드 알고리즘이나 SPFA가 단독으로 쓰이기보다는 MCMF 문제를 풀기 위해 사용하는 경우가 많다.

'Algorithm > H. Trees & Graphs' 카테고리의 다른 글

120. Dial's Algorithm  (0) 2022.03.09
119. 0-1 BFS  (0) 2022.03.07
117. Floyd-Warshall  (0) 2022.03.06
116. Bellman-Ford  (0) 2022.03.01
115. Dijkstra  (0) 2022.02.25