그림으로 먼저 그려보심이 어떠하실지요..
이 문제의 목표는 덩어리들에서 cycle을 검출하는 건데요.
예를 들어서
2 -> 3 -> 4 -> 6 -> 3 -> ... 이런 식으로 있다고 생각해 봅시다.
이 경우 dfs(2)가 먼저 호출이 될 텐데요. 이 때 visited[2] = 1이 됩니다.
여기서 visit는 2가지 역할을 하는데요.
하나는 방문했냐. 안 했냐?
또 하나는 방문했다면 몇 번째로 방문했느냐? 를 나타내는 겁니다.
그렇게 따지면 visit[3] = 2, visit[4] = 3, visit[5] = 4, visit[3] = ?
다시 3을 방문한 시점에서 cnt는 5가 됩니다. 그런데, 3부터 사이클이 시작된 건 맞습니다.
3은 몇 번째로 방문했냐. 2번째로 방문했습니다.
그렇기 때문에, 요소 내에 있는 사이클의 크기는 3이 되죠. 여기까지는 이해하셨나요?
lmcoa15 6년 전
혼자서 해결하려다가 도저히 안되서 다른 분들이 하신거를 참고하여 코드를 작성했습니다.
소스코드를 간단하게 말씀드리면 ans는 사이클이 존재하는 것의 노드 개수이고
vec는 문제에 제시된 각각의 i번 별로 가리키는 node이고 visited는 방문을 확인함과 동시에 dfs를 돌때 몇번째로 방문했는지
나타내는 부분입니다. first_location은 dfs를 돌때 맨 처음에 전달한 시작 node를 각각의 위치에 저장해주는 부분입니다.
그리고 dfs함수내의 start_node는 처음 시작한 node, current_node는 호출할 때마다 가리키는 node이고
cnt는 현재 위치에서 이동할 때마다 몇번째로 방문했는지를 나타내기 위한 변수입니다.
우선 아래의 부분에서 dfs부분에서 사이클을 추려내기 위해 현재까지 이동한 지점에서 다음 노드의 visited값이 0이 아니면,
사이클이 존재한다고 가정하고 0이 아닌 부분의 visited값( 이전에 저장한 cnt값)을 빼서 사이클의 개수가
몇 개인지 구하는 방식은 이해했습니다.
하지만 이해가 되지 않는 부분은
첫번째 if문에서 first_location에 저장된 첫번째 노드를 왜 start_node와 비교하는지 이해가 되지 않습니다.
만약에 처음으로 dfs를 호출하면 매번 start_node를 first_location에 저장할텐데 굳이 start_node를 다시 비교해서 다르면
0을 리턴하는지... 분명히 반례가 존재해서 이렇게 하는거 같은데 이 부분에서 아마 막혀서 해결하지 못했던 것 같습니다.
혹시 그 이유를 알고 계시면 답변 부탁드리겠습니다. 그리고 마지막으로 dfs에서 if문 바깥에 보시면 그냥 dfs를 호출하는데
원래 return dfs(start_node, current_node, cnt + 1); 를 해줘서 값을 넘겨줘야 하는데 return 안해줘도 정상적으로
값이 나오더라구요.. 이부분도 좀 이해가 되지않는데 혹시 이유를 알고 계시면 답변 부탁드리겠습니다.
두서없이 써서 무엇을 물어보려는지 이해가 되지않으실까봐 그냥 요약해서 정리하면
1. dfs 함수의 if문 안에 존재하는 if문에서 first_location[current_node]와 start_node를 비교하는 이유
2. dfs 함수에서 마지막에 return dfs(start_node, current_node, cnt + 1);를 해줘야 하는데 그냥 dfs(start_node, current_node, cnt + 1);
를 써도 답이 출력되는 이유
입니다.