2024. 6. 28. 15:52ㆍ알고리즘/문제풀이
https://www.acmicpc.net/problem/1707
문제를 좀 분석해 보자면 간선의 수는 200000, 정점의 수는 20000, 테스트 케이스 5개이다. 시간 복잡도는 꽤나 여유로워 보이니 문제를 분석해 보았다. 그래프를 두 집합으로 분할하되, 분할된 집합에서 인접하는 노드가 없게끔 분할하면 된다.
가장 먼저 떠오르는건 흐름은 다음과 같았다.
- 시작점 start를 한 집합에 넣고, 인접한 점은 다른 집합에 넣는다.
- 방문하지 않은 점 next에 대해 똑같이 1번을 수행한다.
이렇게 떠올랐는데 굉장히 큰 오류들이 있었다.
먼저 next는 첫 번째 단계의 start와 연관되어 있을 수 있었다. 즉, 맨 처음 시작점의 인접한 점과 그다음 방문하지 않은 점이 인접하다면? 인접하지 않다면? 모두 다른 방향으로 풀이를 진행해야 할 것이다. 따라서 그냥 순서대로 방문하는 게 아니라, bfs가 필요하다고 생각했다.
- start에 대해 bfs를 수행하면서 집합을 나눈다. 이 과정에서 이분 그래프가 맞는지 아닌지 체크한다.
- 그 다음 방문하지 않은 점은 start와는 전혀 무관한 그래프이다. 연결되어 있지 않으므로 1번과 똑같이 bfs를 하면서 집합을 나눌 수 있다.
bfs가 갑자기 왜 떠올랐을까? 이 부분이 좀 중요한 것 같은데, bfs가 필요한 상황을 외우는 게 아니다. 현재 시작점 start와 인접한 점들을 집합으로 나누어야 하는데, 한 번 인접한 게 아니라 두 번, 세 번 인접 즉 연결되어 있는 그래프를 한 번에 집합으로 나누어야 한다.
여기서 떠오른게 bfs인 것이다. start와 바로 인접한 점을 다른 집합에 넣고, 다음 bfs step에서 또 다른 집합(start와 같은 집합)에 넣고,... 이런 식으로 뭔가 퍼져나가듯이 집합을 나누고 이분 그래프인지 체크하고 이런 흐름에서 bfs를 포착한 것이고 더 정확히는 큐를 포착한 것이다!
너무 겁먹지 말고 차근 차근 떠올려보면 해결할 수 있다.
/** 그래프 1707 이분 그래프 **/
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
using namespace std;
int K, v, e;
int group[20100];
vector<int> g[20100];
string solve()
{
fill(group, group + v + 1, -1);
// 첫 번째 점을 시작으로 인접한 점의 집합을 1로, 본인은 0으로 만든다.
// 첫 번째 점과 인접한 점을 큐에 넣는다.
// 큐에서 뺀 점에 대해 인접한 점의 집합을 0으로 만드는데, 1이 있으면 이분 그래프가 아닌 것이다.
for (int i = 1; i <= v; i++)
{
if (group[i] != -1)
continue;
queue<int> q;
q.push(i);
group[i] = 0;
while (!q.empty())
{
int cur = q.front();
q.pop();
for (auto next : g[cur])
{
if (group[next] != -1)
{
if (group[next] == group[cur])
return "NO\n";
else
continue;
}
group[next] = 1 - group[cur];
q.push(next);
}
}
}
return "YES\n";
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> K;
while (K--)
{
cin >> v >> e;
for (int i = 1; i <= v; i++)
g[i].clear();
for (int i = 0; i < e; i++)
{
int a, b;
cin >> a >> b;
g[a].push_back(b);
g[b].push_back(a);
}
cout << solve();
}
}
'알고리즘 > 문제풀이' 카테고리의 다른 글
[백준] 20955번: 민서의 응급 수술 - 그래프를 트리로 바꾸기 (0) | 2024.07.09 |
---|---|
[백준] 4803번: 트리 - 무방향 그래프에서 DFS로 사이클 찾기 (0) | 2024.07.02 |
[BOJ] C++ 3758: KCPC - 정렬 기준 설정하기 (1) | 2024.02.27 |
[BOJ] C++ 20920: 영단어 암기는 괴로워 - 세 가지 기준의 우선순위 큐 (0) | 2024.02.18 |
[BOJ] C++ 13305: 주유소 - 우선순위 큐와 그리디 알고리즘 (1) | 2024.02.16 |