DFS로 덩어리 개수 찾고, BFS로 최단 거리 찾을 줄 알면 된다고 생각했다가 코테에서 사이클 관련 문제가 나와서 큰코다쳤다.
시험 시간에 즉흥적으로 사이클 찾다가 실패해서 중간에 포기했다. DFS로 될 것 같아서 계속 시도하다가..ㅎㅎ 시간은 날리고 문제는 못풀어서 손해가 컸음!! 사이클 찾는 것도 경험해봐야 시험 시간에도 빨리빨리 기억이 날 것이다.
우선 그림을 보고 직관적으로 생각해보자면, 시작 노드(여기서는 1)로부터 일렬로 지나가본다.
1 -> 2 -> 3, 그리고 여기서 5를 갈 수도 있고 4를 갈 수도 있다. 각각 가보겠다.
3 -> 5. (끝)
3 -> 4 -> 2? 방문했던 노드를 다시 만났다. 사이클이 있음을 알 수 있다.
이걸 코드로 옮겨야 한다.!! + 사이클에 해당하는 노드를 찾아야 한다.
#include <iostream>
#include <vector>
int V, E;
std::vector<std::vector<int>> graph;
std::vector<int> cycle;
std::vector<int> visited;
int cyclestart = 0;
bool Find(int curnode, int parent)
{
visited[curnode] = 1;
for (int nextnode : graph[curnode])
{
if (nextnode == parent) continue;
if (visited[nextnode] == 0)
{
if (Find(nextnode, curnode))
{
if (cyclestart != -1) // 사이클 시작된 경우
{
cycle.push_back(curnode);
if (curnode == cyclestart) // 사이클 시작점으로 돌아온 경우 사이클 종료를 의미
{
cyclestart = -1;
}
}
return true;
}
}
else if (visited[nextnode] == 1)
{
cyclestart = nextnode;
cycle.push_back(curnode);
return true;
}
}
return false;
}
int main()
{
std::cin >> V >> E;
graph.resize(V + 1);
visited.resize(V + 1);
for (int i = 0; i < E; ++i)
{
int v1, v2;
std::cin >> v1 >> v2;
graph[v1].push_back(v2);
graph[v2].push_back(v1);
}
Find(1, 1);
std::cout << "사이클 : ";
for (int c : cycle)
{
std::cout << c << " ";
}
return 0;
}
그래프 한 덩어리 외에도 탐색하려면 for문으로 모든 정점을 돌아 'visited[i] == 0' 인 곳을 모두 Find로 들어가줘야 한다.