본문 바로가기

알고리즘/BOJ

1504번

1504번 - 특정한 최단 경로


1번 정점에서 N번 정점까지 가는데 A,B를 무조건 거쳐야 한다.


그러기 위해서는 1->A->B->N 이거나 1->B->A->N 이어야 한다.

( 문제에서 간선을 여러번 지나쳐도 되기 때문에, 다른 케이스는 고려하지 않아도 된다.)


따라서 첫번째 경우나, 두번째 경우에서 최솟값을 찾으면 된다.


편의상 D[i][j] 를 i 에서 j 가는 최단거리라고 하면 ,


첫번째 경우는 D[1][A] + D[A][B] + D[B][N] 이고,


두번째 경우는 D[1][B] + D[B][A} + D[A][N] 이 된다.


여기서 D[A][B]=D[B][A] 이므로 한번의 다익스트라 알고리즘으로 구하고,


D[1][A] 와 D[1][B]는 시작점을 1로 하는 다익스트라 알고리즘으로 구하고,


D[B][N]=D[N][B], D[A][N]=D[N][A] 이므로 시작점을 N으로 하는 다익스트라 알고리즘으로 구한다.


총 세번의 다익스트라 알고리즘으로 구할 수 있다.


모든 쌍들을 구해서 풀 수도 있으므로 플로이드-워셜 알고리즘으로 한꺼번에 구할 수도 있다.


### int 형 변수 범위 넘어가는 거 꼭 조심!


<정답 코드 - 다익스트라 (priority Queue 사용)>


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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int INF = 987654321;
int n, e, m1, m2;
long long from1toM1, from1toM2, fromM1toM2, fromNtoM1, fromNtoM2;
void dikjstra(int start, vector<vector<pair<intint>>> v, vector<int> dist)
{
    for (int i = 1; i <= n; i++)
    {
        dist[i] = INF;
    }
 
    priority_queue<pair<intint>> q;
 
    dist[start] = 0;
    q.push({ start,0 });
 
    while (!q.empty())
    {
        int now = q.top().first;
        int cost = -q.top().second;
        q.pop();
 
        if (cost > dist[now]) 
        {
            continue;
        }
 
        for (int i = 0; i < v[now].size(); i++)
        {
            int next = v[now][i].first;
            int w = v[now][i].second;
 
            if (dist[next] > cost + w && cost != INF)
            {
                dist[next] = cost + w;
                q.push({ next,-dist[next] });
            }
        }
    }
 
    if (start == 1)
    {
        from1toM1 = dist[m1];
        from1toM2 = dist[m2];
    }
 
    if (start == m1)
    {
        fromM1toM2 = dist[m2];
    }
 
    if (start == n)
    {
        fromNtoM1 = dist[m1];
        fromNtoM2 = dist[m2];
    }
 
    return;
}
int main()
{
    //freopen("input.txt", "r", stdin);
    scanf("%d %d"&n, &e);
    vector<vector<pair<intint>> > v(n+1);
    vector<int> dist(n+1);
 
    int start = 1, dest = n;
 
    for (int i = 0; i < e; i++)
    {
        int a, b, c;
        scanf("%d %d %d"&a, &b, &c);
        v[a].push_back({ b,c });
        v[b].push_back({ a,c });
    }
    scanf("%d %d"&m1, &m2);
 
    dikjstra(1,v,dist);
    dikjstra(m1,v,dist);
    dikjstra(n,v,dist);
    
    long long x = from1toM1 + fromM1toM2 + fromNtoM2;
    long long y = from1toM2 + fromM1toM2 + fromNtoM1;
 
    if (x >= INF && y >= INF)
    {
        printf("-1\n");
    }
    else
    {
        printf("%d\n", min(x, y));
    }
 
    return 0;
}
cs

<정답 코드 - 다익스트라(priority Queue 사용하지 않음)>

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int INF = 987654321;
int n, e, m1, m2;
long long from1toM1, from1toM2, fromM1toM2, fromNtoM1, fromNtoM2;
void dikjstra(int start, vector<vector<pair<intint>>> v, vector<int> dist,vector<bool> visited)
{
    for (int i = 1; i <= n; i++)
    {
        dist[i] = INF;
    }
 
    dist[start] = 0;
 
    while (true)
    {
        int now;
        int smallest = INF;
 
        for (int i = 1; i <= n; i++)
        {
            if (!visited[i] && dist[i] < smallest)
            {
                now = i;
                smallest = dist[i];
            }
        }
 
        if (smallest == INF)
        {
            break;
        }
 
        visited[now] = true;
 
        for (int i = 0; i < v[now].size(); i++)
        {
            int next = v[now][i].first;
            int cost = v[now][i].second;
 
            if (dist[next] > cost + smallest)
            {
                dist[next] = cost + smallest;
            }
        }
    }
    
 
    if (start == 1)
    {
        from1toM1 = dist[m1];
        from1toM2 = dist[m2];
    }
 
    if (start == m1)
    {
        fromM1toM2 = dist[m2];
    }
 
    if (start == n)
    {
        fromNtoM1 = dist[m1];
        fromNtoM2 = dist[m2];
    }
 
    return;
}
int main()
{
    //freopen("input.txt", "r", stdin);
    scanf("%d %d"&n, &e);
    vector<vector<pair<intint>> > v(n+1);
    vector<int> dist(n+1);
    vector<bool> visited(n + 1);
    int start = 1, dest = n;
 
    for (int i = 0; i < e; i++)
    {
        int a, b, c;
        scanf("%d %d %d"&a, &b, &c);
        v[a].push_back({ b,c });
        v[b].push_back({ a,c });
    }
    scanf("%d %d"&m1, &m2);
 
    dikjstra(1,v,dist,visited);
    dikjstra(m1,v,dist,visited);
    dikjstra(n,v,dist,visited);
    
    long long x = from1toM1 + fromM1toM2 + fromNtoM2;
    long long y = from1toM2 + fromM1toM2 + fromNtoM1;
 
    if (x >= INF && y >= INF)
    {
        printf("-1\n");
    }
    else
    {
        printf("%d\n", min(x, y));
    }
 
    return 0;
}
cs


<정답 코드 - 플로이드 워샬 알고리즘>


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
71
72
73
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
 
long long D[801][801];
const long long INF=987654321;
int main()
{
    int n, e; 
    vector<vector<pair<intint>>> v;
    scanf("%d %d"&n, &e);
    int start = 1, dest = n;
    for (int i = 0; i < e; i++)
    {
        int a, b, c;
        scanf("%d %d %d"&a, &b, &c);
        D[a][b] = c;
        D[b][a] = c;
    }
    int m1, m2;
    scanf("%d %d"&m1, &m2);
 
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (i == j)
            {
                D[i][j] = 0;
            }
            else
            {
                if (D[i][j] == 0)
                {
                    D[i][j] = INF;
                }
            }
        }
    }
 
 
    for (int k = 1; k <= n; k++)
    {
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                if (D[i][j] > D[i][k] + D[k][j])
                {
                    D[i][j] = D[i][k] + D[k][j];
                }
            }
        }
    }
 
    long long ans = D[1][m1] + D[m1][m2] + D[m2][n];
    long long ans2 = D[1][m2] + D[m2][m1] + D[m1][n];
 
    if (ans >= INF && ans2>=INF)
    {
        printf("-1\n");
    }
    else
    {
        printf("%lld\n", min(ans, ans2));
    }
 
 
    
 
    return 0;
}
cs


반응형

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

11404번  (0) 2018.01.03
1753번  (0) 2018.01.02
11779번  (0) 2018.01.02
1916번  (0) 2018.01.02
1865번  (0) 2018.01.02