반응형

문제 출처 :


https://www.acmicpc.net/problem/11780



알고리즘 분석 :


문제 해결에 필요한 사항

1. 플로이드 워셜 알고리즘 :: http://www.crocus.co.kr/search/%ED%94%8C%EB%A1%9C%EC%9D%B4%EB%93%9C

2. 경로 추적


플로이드 워셜 알고리즘을 이용하여 문제를 기본적으로 접근한다.


문제 이름 자체도 플로이드 2이지만, 일단 정점이 100개라는 것을 생각한다면 당연히 플로이드로 접근 할 수 있는 문제이다.


그리고 플로이드 워셜을 통해 기본적인 최단 거리를 구해주고, 마지막으로 경로를 찾아내는 알고리즘을 통해 이 문제를 해결 할 수 있다.


경로 찾는 알고리즘은 주석을 통해 설명을 해 두었다.



소스 코드 : 


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
107
108
109
110
111
112
113
114
115
#include <iostream>
#include <cstdio>
#include <vector>
#include <memory.h>
#include <algorithm>
 
#define INF 1000001
 
using namespace std;
 
int adj[101][101];
int dist[101][101];
int via[101][101];
 
// 경로 찾기
void reconstruct(int u, int v, vector<int> &path)
{
    // u->v로 가는 경유점이 없다면
    if (via[u][v] == 0)
    {
        // u를 담고
        path.push_back(u);
        // u와 v가 다르다면
        if (u != v)
            path.push_back(v); // v를 담는다.
        // u와 v가 같다면 경로는 자기 자신이다.
    }
 
    // u->v로 가는 경유점이 있다면
    else
    {
        // w에 경유점을 담아준다.
        int w = via[u][v];
 
        // u->w(경유점)으로 재귀를 호출한다.
        reconstruct(u, w, path);
        // 재귀에서 위의 if문에 의해 중첩되어 쌓이게 되는 것을 방지한다.
        path.pop_back();        
        // w->v로 재귀를 호출한다.
        reconstruct(w, v, path);
    }
}
int main()
{
    int V;
    scanf("%d"&V);
 
    int E;
    scanf("%d"&E);
 
    for (int i = 1; i <= V; i++)
        for (int j = 1; j <= V; j++)
            i == j ? adj[i][j] = : adj[i][j] = INF;
 
    // 그래프 정보 입력
    for (int i = 0; i < E; i++)
    {
        int from, to, val;
        scanf("%d %d %d"&from, &to, &val);
 
        adj[from][to] = min(adj[from][to], val);
    }
 
    // 플로이드 워셜 알고리즘
    for (int k = 1; k <= V; k++)
        for (int x = 1; x <= V; x++)
            for (int y = 1; y <= V; y++)
            {
                if (adj[x][y] > adj[x][k] + adj[k][y])
                {
                    via[x][y] = k;
 
                    adj[x][y] = adj[x][k] + adj[k][y];
                }
            }
 
    // 플로이드 워셜을 통한 최단거리 표현
    for (int i = 1; i <= V; i++)
    {
        for (int j = 1; j <= V; j++)
            printf("%d ", adj[i][j]);
 
        printf("\n");
    }
 
    // 경로 찾기
    vector<int> path;
    for (int i = 1; i <= V; i++)
    {
        for (int j = 1; j <= V; j++)
        {
            // i == j면 0 출력(자기 자신)
            if (i == j)
            {
                printf("0\n");
                continue;
            }
 
            reconstruct(i, j, path);
 
            // path에 받아온 경로를 출력한다.
            printf("%d ", path.size());
            for (int i = 0; i < path.size(); i++)
                printf("%d ", path[i]);
            printf("\n");
 
            path.clear();
        }
 
    }
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus


반응형

'Applied > 알고리즘 문제풀이' 카테고리의 다른 글

[5427번] 불  (0) 2017.03.31
[4179번] Fire!  (4) 2017.03.31
[1168번] 조세퍼스 문제 2  (0) 2017.03.29
[1017번] 소수 쌍  (0) 2017.03.29
[9466번] 텀 프로젝트  (0) 2017.03.29