CS/baekjoon
[백준 1238번] 파티
hanjongho
2021. 4. 13. 00:06
https://www.acmicpc.net/problem/1238
1238번: 파티
첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 10,000), X가 공백으로 구분되어 입력된다. 두 번째 줄부터 M+1번째 줄까지 i번째 도로의 시작점, 끝점, 그리고 이 도로를 지나는데 필요한 소요시간 Ti가 들어
www.acmicpc.net
풀이)
한 정점에서 다른 한개의 정점이 아니기에 플로이드 와샬로 풀어야 한다고 생각했다. 무한대로 초기화시켜놓고 거쳐가는 모든 경로를 확인하면서 최단경로를 확인하면 해결될 것이라 생각했는데, 시간초과가 났다. O(N^3)이여서 1000일경우 10억이 되기에 안된다는 생각을 그때 깨달았다. 하지만 질문검색에서 무한대인경우를 탐색을 진행하지 않는 방식으로 잘 가지치기를 하면 통과한다는 글이 있었고 해결할 수 있었다. 물론 운이 좋았다고 생각했고, 다익스트라 알고리즘을 이용해서 다시 한번 풀어보았다. 다익스트라 알고리즘 같은 경우 시작점 -> 마을 + 마을 -> 시작점의 최단경로가 가장 짧은 곳은 구하는 방식으로 접근하였다.
1. 플로이드 와샬을 이용한 풀이
#include <iostream>
using namespace std;
int N, M, X, ans = 0;
int arr[1001][1001];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> N >> M >> X;
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
arr[i][j] = 2e8;
for (int i = 0; i < M; i++)
{
int s, e, c;
cin >> s >> e >> c;
arr[s][e] = c;
}
for (int k = 1; k <= N; k++)
{
for (int i = 1; i <= N; i++)
{
if (arr[i][k] == 2e8)
continue;
for (int j = 1; j <= N; j++)
arr[i][j] = min(arr[i][j], arr[i][k] + arr[k][j]);
}
}
for (int i = 1; i <= N; i++)
if (i != X && arr[i][X] != 2e8 && arr[X][i] != 2e8)
ans = max(ans, arr[i][X] + arr[X][i]);
cout << ans << "\n";
return (0);
}
2. 다익스트라 알고리즘을 이용한 풀이
#include <iostream>
#define INF 2e8
using namespace std;
int N, M, X, x, y, z, cnt = 0, ans = -1;
int cost[1001][1001], cost_[1001][1001], result[2][1001], visited[1001];
int findMin(int start)
{
int tmp = INF, idx = 0;
for (int i = 1; i <= N; i++)
{
if (!visited[i] && result[cnt][i] < tmp)
{
tmp = result[cnt][i];
idx = i;
}
}
visited[idx] = 1;
return (idx);
}
void dijkstra(int start)
{
for (int i = 1; i <= N; i++)
{
result[cnt][i] = INF;
visited[i] = 0;
}
result[cnt][start] = 0;
for (int i = 1; i <= N; i++)
{
int t = findMin(start);
for (int j = 1; j <= N; j++)
{
if (cnt == 0 && cost[t][j] != 0 && result[cnt][t] + cost[t][j] < result[cnt][j])
result[cnt][j] = result[cnt][t] + cost[t][j];
else if (cnt == 1 && cost_[t][j] != 0 && result[cnt][t] + cost_[t][j] < result[cnt][j])
result[cnt][j] = result[cnt][t] + cost_[t][j];
}
}
cnt = 1;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> N >> M >> X;
for (int i = 1; i <= M; i++)
{
cin >> x >> y >> z;
cost[x][y] = z;
cost_[y][x] = z;
}
dijkstra(X);
dijkstra(X);
for (int i = 1; i <= N; i++)
if (result[0][i] + result[1][i] > ans)
ans = result[0][i] + result[1][i];
cout << ans << "\n";
return (0);
}
제 코드는 절대 완벽하지 않습니다
더 좋은 풀이방법 혹은 코드에 관한 질문이 있으시면 언제든 댓글주세요!