BOJ 백준 1613 : 역사
Updated:
시작하면서
이번 문제는 플로이드-와샬 알고리즘(FloydWarshall Algorithm) 을 사용해 해결하는 문제이다.
문제 이해
이 문제는 사실 플로이드-와샬로 해결하지 않아도 되보이는 문제이다. 단순하게 문제를 만들면,
- 전후 관계를 간선으로 만들고
- 간선을 모두 이어둔 그래프를 만든 후
- 앞의 사건이 먼저인지, 뒤의 사건이 먼저인지를 확인
이렇게 3개의 과정을 좀 더 효율적인 방법으로 해결하면 되지만, 플로이드-와샬 알고리즘을 공부하면서 해결하는 문제이므로 플로이드-와샬 알고리즘으로 해결했다. 방법은 다음과 같다.
- 사건의 전후 관계를 나타낼 그래프를 만들고, 모두 INT_MAX로 초기화한다.
- 사건의 전후 관계를 인풋으로 받아서, 그래프에 1의 값으로 넣어준다.
- 인풋을 전부 넣은 후에는 플로이드-와샬 알고리즘을 통해 그래프를 변경한다.
- 조건에 맞게 답을 출력한다.
여기서 문제에만 최적화하려면 굳이 그래프에 int를 사용하지 않고, 단순히 연결되어 있는지를 계속 확인하면서 bool 값을 사용해도 된다. 하지만 굳이 그렇게까지도 하지 않고, 플로이드-와샬 그대로 유지하겠다.
해결
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <math.h>
#include <limits.h>
using namespace std;
void Input(vector<vector<int>> &graph)
{
int n, k;
cin >> n >> k;
graph.resize(n + 1);
for (int i = 1; i <= n; i++)
{
graph[i].resize(n + 1);
for (int j = 1; j <= n; j++)
{
graph[i][j] = (i == j) ? 0 : INT_MAX;
}
}
for (int i = 0; i < k; i++)
{
int a, b;
cin >> a >> b;
graph[a][b] = 1;
}
}
void DoFloydWarshall(vector<vector<int>> &graph)
{
int n = graph.size() - 1;
for (int t = 1; t <= n; t++)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (graph[i][t] == INT_MAX)
{
continue;
}
if (graph[t][j] == INT_MAX)
{
continue;
}
if (graph[i][j] > graph[i][t] + graph[t][j])
{
graph[i][j] = graph[i][t] + graph[t][j];
}
}
}
}
}
void PrintAnswer(const vector<vector<int>>& graph)
{
int s;
cin >> s;
for (int i = 0; i < s; i++)
{
int a, b;
cin >> a >> b;
if (graph[a][b] == INT_MAX)
{
if (graph[b][a] != INT_MAX)
{
cout << "1\n";
}
else
{
cout << "0\n";
}
}
else
{
cout << "-1\n";
}
}
}
int main()
{
// sync off
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// sync off
vector<vector<int>> graph;
Input(graph);
DoFloydWarshall(graph);
PrintAnswer(graph);
return 0;
}
Leave a comment