Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- union-find
- 유니온파인드
- BFS
- DP
- Algospot
- 너비우선탐색
- 백트래킹
- 이분탐색
- DFS
- 문자열
- 알고스팟
- 스택
- Greedy
- 재귀
- 분할정복
- 동적계획법
- BOJ
- 종만북
- priority_queue
- acm
- stack
- 다이나믹프로그래밍
- 그리디
- 완전탐색
- 백준
- 알고리즘문제해결전략
- 누적합
- backtracking
- 세그먼트트리
- 분리집합
Archives
- Today
- Total
DAMPER's blog
11780. 플로이드 2 본문
728x90
https://www.acmicpc.net/problem/11780
11780번: 플로이드 2
첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가
www.acmicpc.net
문제 설명
문제 제목처럼 플로이드-워셜 알고리즘을 한 뒤, 경로 추적을 통해 i -> j 로 가는 최소비용의 경로를 출력하는 문제이다.
solution
먼저 플로이드-워셜 알고리즘을 통해 최소비용 테이블은 만든다.
i에서 j로 가는 비용을 i -> k -> j 비용으로 갱신할 때, 추적 테이블에 i -> j 갈 때 k를 거쳐간다고 저장한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
void floyd(vvi &dist, vvi &trace)
{
for (int k = 1; k <= N; k++)
{
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
if (dist[i][j] > dist[i][k] + dist[k][j])
{
dist[i][j] = dist[i][k] + dist[k][j];
trace[i][j] = k;
}
}
}
}
}
|
cs |
최소비용 테이블과 추적 테이블이 다 채워지면 분할정복으로 경로 추적에 들어간다.
startn에서 endn 으로 갈 때, mid를 거쳐서 가므로 startn -> mid 경로를 찾고, mid -> endn 경로를 찾는다.
이 때 pv 벡터에 mid가 두 번 들어가니 중간에 pop_back을 해준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
void find(int startn, int endn, vvi &trace, vi &pv)
{
int mid = trace[startn][endn];
if (mid == 0)
{
pv.emplace_back(startn);
pv.emplace_back(endn);
return;
}
find(startn, mid, trace, pv);
pv.pop_back();
find(mid, endn, trace, pv);
}
|
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
#include <bits/stdc++.h>
using namespace std;
#define swap(a, b) (a) ^= (b) ^= (a) ^= (b)
#define endl '\n'
#define int long long
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vector<int>>;
const double EPS = 1e-9;
const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, 1, -1};
int N, M;
void floyd(vvi &dist, vvi &trace)
{
for (int k = 1; k <= N; k++)
{
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
if (dist[i][j] > dist[i][k] + dist[k][j])
{
dist[i][j] = dist[i][k] + dist[k][j];
trace[i][j] = k;
}
}
}
}
}
void find(int startn, int endn, vvi &trace, vi &pv)
{
int mid = trace[startn][endn];
if (mid == 0)
{
pv.emplace_back(startn);
pv.emplace_back(endn);
return;
}
find(startn, mid, trace, pv);
pv.pop_back();
find(mid, endn, trace, pv);
}
int32_t main()
{
cin.sync_with_stdio(NULL);
cin.tie(NULL);
cout.tie(NULL);
cin >> N >> M;
vvi dist(N + 1, vector<int>(N + 1, INT_MAX));
vvi trace(N + 1, vector<int>(N + 1, 0));
int a, b, cost;
for (int i = 0; i < M; i++)
{
cin >> a >> b >> cost;
dist[a][b] = min(dist[a][b], cost);
}
for (int i = 1; i <= N; i++)
dist[i][i] = 0;
floyd(dist, trace);
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
cout << (dist[i][j] >= INT_MAX ? 0 : dist[i][j]) << ' ';
}
cout << endl;
}
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
if (i == j || dist[i][j] >= INT_MAX)
{
cout << 0 << endl;
continue;
}
vector<int> ptrace;
find(i, j, trace, ptrace);
cout << ptrace.size() << ' ';
for (int K : ptrace)
cout << K << ' ';
cout << endl;
}
}
return 0;
}
|
cs |
728x90
'Problem Solving > BOJ 문제풀이' 카테고리의 다른 글
7869. 두 원 (0) | 2022.07.16 |
---|---|
3015. 오아시스 재결합 (0) | 2022.07.09 |
1509. 팰린드롬 분할 (0) | 2022.07.04 |
1007. 벡터 매칭 (0) | 2022.07.04 |
13140. Hello World! (0) | 2022.01.13 |