오늘을 개힘들고 개 슬픈 유니온 파인드 알고리즘에 대해서 알아보도록 하즈아
Union: 서로 다른 두 개의 집합을 하나의 집합으로 병합하는 연산을 말한다. 이 자료구조에서는 상호 배타적 집합만을 다루므로 Union 연산은 합집한 연산과 같다.
그냥 합치기라 생각하도록 하자
Find: 하나인 원소가 어떤 집합에 속해있는지를 판단한다.
찾기라고 생각해보자
100번 설명보다 1번의 실전이 익히기 훨씬 쉽다.
하지만 우리는 이것이 dfs랑 비슷하다는것을 알고있다(아마)
그러기 때문에 굳이굳이 dfs를 사용하여 만들어보자

유니온 파인드를 쓰는게 정석이지만 만능 DFS로 풀어보도록하자.
def dfs(student, target, visited): #dfs라는 함수를 만들어준다.
if student == target: #target노드까지 갔다면 True를 반환해준다.
return True
visited.add(student) #방문을 하면 visited안에 추가해준다.
for friend in graph[student]: #내가 있는 노드의 연결되어있는 노드들을 하나하나씩 찾아본다.
if friend not in visited: #만약 한번도 이 노드를 들르지않았다면
if dfs(friend, target, visited): #방문하지않았다면 노드를 따라 쭉 간다.
return True #이게 없다면 노드를 찾았는데도 반복문이 끝날때까지 True가 나오지않아서 False가 뜬다.
return False #반복문이 돌때까지 True가 나오지않으면 False를 리턴해준다.
N, M = map(int, input().split()) #학생수와 입력받을 갯수를 입력받는다.
graph = {i: [] for i in range(1, N + 1)} #사전 자료형으로 학생수만큼 만들어준다 keys는 1부터 학생수만큼이고 value는 빈 배열이다.
for i in range(M): #반복문을 돌린다
a, b = map(int, input().split()) #입력을 받고 int로 바꾸어준다.
graph[a].append(b) #graph의 a라는 키값에 b를 추가해준다.
graph[b].append(a) #graph의 a라는 키값에 b를 추가해준다.
x, y = map(int, input().split()) #친구인지 확인해보고 싶은 친구 번호를 적는다.
visited = set() #빈 집합을 생성한다.
if dfs(x, y, visited): #True면 YES로 출력하고 아니면 NO로 출력한다.
print("YES")
else:
print("NO")
4번 그림 설명
지금상황은 1이랑 4가 친구인지 확인하는 상황이다.

이렇게 연결되어있다.
{1:[2,3],2:[5],3:[4],4:[3],5:[2]}
가 그래프상황이다.
1과 4를 dfs함수에 넣어주니까
방문한 노드에 1을 넣어준다.
그리고 for문을 돈다.
2번은 방문을 안했기때문에

2번으로 이동한다 방문한 노드에 2를 넣어준다.
다시 방문한 노드에 2를 넣어준다.
다시 for문을 돈다.5번은 방문을 안했기때문에
방문한노드에 5를 넣어주고
for문을 돌지만 돌게 없기때문에 false가 나온다.
그러기 때문에 다시 2로 돌아간다.
false가 리턴되었기때문에 넘어간다.
하지만 2번에도 for문이 끝났기때문에 다시 뒤로 돌아간다.
1번 노드로 돌아왔지만 false가 떳다.
하지만 for문은 끝나지 않았고 3번은 방문을 안했기때문에 3번으로 간다.

방문한 노드에 3을 넣어주고
for문을 실행시켜준다.
4번은 방문을 안했기때문에

4번으로 가준다.
그리고 찾고싶은 타겟이랑 지금 있는 곳이랑 같으니까 트루를 리턴해준다.
리턴이기 때문에
3번노드로 가주고
3번노드도 트루로 리턴되기때문에
다시 1번 노드로 가고
트루로 또 리턴되기때문에
결국은 YES가 뜬다.