[백준 4192] 친구 네트워크 (python 풀이)
1. 문제
민혁이는 소셜 네트워크 사이트에서 친구를 만드는 것을 좋아하는 친구이다. 우표를 모으는 취미가 있듯이, 민혁이는 소셜 네트워크 사이트에서 친구를 모으는 것이 취미이다.
어떤 사이트의 친구 관계가 생긴 순서대로 주어졌을 때, 두 사람의 친구 네트워크에 몇 명이 있는지 구하는 프로그램을 작성하시오.
친구 네트워크란 친구 관계만으로 이동할 수 있는 사이를 말한다.
2. 입력
첫째 줄에 테스트 케이스의 개수가 주어진다. 각 테스트 케이스의 첫째 줄에는 친구 관계의 수 F가 주어지며, 이 값은 100,000을 넘지 않는다. 다음 F개의 줄에는 친구 관계가 생긴 순서대로 주어진다. 친구 관계는 두 사용자의 아이디로 이루어져 있으며, 알파벳 대문자 또는 소문자로만 이루어진 길이 20 이하의 문자열이다.
3. 출력
친구 관계가 생길 때마다, 두 사람의 친구 네트워크에 몇 명이 있는지 구하는 프로그램을 작성하시오.
4. 포인트
- 기초가 되는 알고리즘인 union - find 알고리즘을 익혀두자
- dictionary 의 key error 를 막기 위해서는 key를 통한 접근전에 not in 연산자를 통한 검사가 필요하다
4. 문제 풀이
그래프 부분중 크루스칼 알고리즘 공부중 학습했던 union - find 알고리즘으르 통해 풀 수 있는 문제였다.
딕셔너리에 각각의 이름을 key 로 추가하고 값에는 parent 값을 넣어줌으로써 추후 parent를 parent node로 트리가 형성된다. 이렇게 parent를 통해 찾아나가는 것이 find 알고리즘을 이용한 것이고 , 서로 다른 집합을 합치는 uion 함수는 union 알고리즘을 이용한 것이다. 또한 문제에서 요구하는 네트워크에 몇명이 포함 되어 있는지를 반환하기 위해 각 parent를 key로하는 number dictionary 를 만들었다.
number는 parent 를 key로 그리고 parent의 네트워크 크기를 value로 하기때문에 최종적인 값을 구할때는 입력값의 parent를 구해서 number로 조회함을 잊지말자
주의할껀 해당코드 부분이다. 이부분이 빠져도 동작에는 문제없지만 실제로 제출해봤을때 시간초과가 뜬다. 이유를 추론했을때 중간 저 코드로 인해서 range(or depth)가 모두 1이 되어 시간이 많이 단축되는 것 같다.
# 친구 네트워크
def find(name):
if name == dic[name]:
return name
else:
p = find(dic[name])
## 해당코드 ##
dic[name] = p
######
return p
def union(name1, name2):
parent1 = find(name1)
parent2 = find(name2)
if parent1 != parent2 :
dic[parent2] = parent1
number[parent1] += number[parent2]
# parent2 의 부모값을 parent1 으로 바꿔줌으로써
# 두 tree를 합쳤다고 볼 수 있다.
case = int(input())
for i in range(case):
group = int(input())
dic = dict()
number = dict()
for j in range(group):
name1 , name2 = input().split()
if name1 not in dic:
dic[name1] = name1
number[name1] = 1
if name2 not in dic:
dic[name2] = name2
number[name2] = 1
union(name1 , name2 )
parent = find(name1 )
print(number[parent])