기술 블로그

SPFA (Shortest Path Faster Algorithm) 본문

알고리즘

SPFA (Shortest Path Faster Algorithm)

parkit 2019. 6. 1. 18:24
728x90
반응형

참고 및 출처 :

https://www.crocus.co.kr/1089?category=209527 [Crocus]









SPFA (Shortest Path Faster Algorithm)


1. 벨만포드 알고리즘의 성능을 향상시킨 알고리즘


2. SPFA는 음수 간선에도 문제없이 돌아가기 때문에 MCMF에서 자주 쓰인다.


3. 벨만포드는 모든 간선에 대해 업데이트를 진행하지만,

SPFA는 바뀐 정점과 연결된 간선에 대해서만 업데이트를 진행한다는 것이다.


4. 바뀐 정점은 큐를 이용해서 관리하고, 큐에 해당 정점이 있는지 없는지는 배열을 이용해서 체크한다.









활용 문제 : https://www.acmicpc.net/problem/11657







벨만포드 알고리즘으로 푼 타임머신 문제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <bits/stdc++.h>
 
using namespace std;
 
#define INF 987654321
 
int dist[501], inQ[501], n, m;
 
vector<pair<intint> > v[501];
 
queue<int> q;
 
int main(void)
{
    int s, e, w;
 
    scanf("%d %d"&n, &m);
 
    for (int i = 0; i < m; i++)
    {
        scanf("%d %d %d"&s, &e, &w);
        v[s].push_back({ e, w });
    }
 
    fill(dist, dist + 501, INF);
 
    dist[1= 0;
 
    for (int i = 0; i < n; i++// 모든 간선
        for (int j = 1; j <= n; j++// 현재 간선
            for (int k = 0; k < v[j].size(); k++)
            {
                int next = v[j].at(k).first;
 
                if (dist[next] > dist[j] + v[j].at(k).second && dist[j] != INF)
                {
                    if (i == n - 1// 음수 사이클, 예제 2번
                    {
                        printf("-1\n");
                        return 0;
                    }
 
                    dist[next] = dist[j] + v[j].at(k).second;
                }
            }
 
    for (int i = 2; i <= n; i++)
        printf("%d\n", dist[i] == INF ? -1 : dist[i]);
 
    return 0;
}
cs










SPFA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <bits/stdc++.h>
 
using namespace std;
 
#define INF 987654321
 
int dist[501], cycle[501], n, m;
 
bool inQ[501];
 
vector<pair<intint> > v[501];
 
queue<int> q;
 
int main(void)
{
    int s, e, w;
 
    scanf("%d %d"&n, &m);
 
    for (int i = 0; i < m; i++)
    {
        scanf("%d %d %d"&s, &e, &w);
        v[s].push_back({ e, w });
    }
 
    fill(dist, dist + 501, INF);
 
    dist[1= 0;
    q.push(1); // 시작 정점 및 SPFA를 위한 queue
    ++cycle[1];
 
    while (!q.empty())
    {
        int here = q.front();
 
        q.pop();
 
        inQ[here] = false;
 
        for (auto i : v[here])
        {
            int next = i.first;
            
            if (dist[next] > dist[here] + i.second && dist[here] != INF)
            {
                dist[next] = dist[here] + i.second;
 
                if (!inQ[next]) // 만약 다음 정점이 Queue에 없다면
                {
                    ++cycle[next];
 
                    if (cycle[next] >= n) // 음수 사이클
                    {
                        printf("-1\n");
                        return 0;
                    }
 
                    q.push(next);
                    inQ[next] = true;
                }
            }
        }
    }
 
    for (int i = 2; i <= n; i++)
        printf("%d\n", dist[i] == INF ? -1 : dist[i]);
 
    return 0;
}
cs


















728x90
반응형

'알고리즘' 카테고리의 다른 글

Next Greater Element(NGE)  (0) 2019.07.06
2차원 배열을 함수 인자로 전달(포인터)  (0) 2019.07.01
MCMF(Minimum Cost Maximum Flow)  (0) 2019.05.23
LCS(Longest Common Subsequence)  (0) 2019.05.23
Prefix Sum  (0) 2019.05.08