자료구조 & 알고리즘/BOJ 문제풀이

[백준 4192] 친구 네트워크 (python 풀이)

쉽코기 2021. 9. 12. 19:03

 

1. 문제 

민혁이는 소셜 네트워크 사이트에서 친구를 만드는 것을 좋아하는 친구이다. 우표를 모으는 취미가 있듯이, 민혁이는 소셜 네트워크 사이트에서 친구를 모으는 것이 취미이다.

어떤 사이트의 친구 관계가 생긴 순서대로 주어졌을 때, 두 사람의 친구 네트워크에 몇 명이 있는지 구하는 프로그램을 작성하시오.

친구 네트워크란 친구 관계만으로 이동할 수 있는 사이를 말한다.

2. 입력

첫째 줄에 테스트 케이스의 개수가 주어진다. 각 테스트 케이스의 첫째 줄에는 친구 관계의 수 F가 주어지며, 이 값은 100,000을 넘지 않는다. 다음 F개의 줄에는 친구 관계가 생긴 순서대로 주어진다. 친구 관계는 두 사용자의 아이디로 이루어져 있으며, 알파벳 대문자 또는 소문자로만 이루어진 길이 20 이하의 문자열이다.

3. 출력

친구 관계가 생길 때마다, 두 사람의 친구 네트워크에 몇 명이 있는지 구하는 프로그램을 작성하시오.

 


4. 포인트

  1.  기초가 되는 알고리즘인 union - find 알고리즘을 익혀두자   
  2.  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])