happyso
study with happyso
happyso
전체 방문자
오늘
어제
  • 분류 전체보기 (302)
    • GIT (3)
    • 컴퓨터 기본 개념 (29)
    • 알고리즘 (125)
      • 알고리즘 문제 (115)
      • 알고리즘 개념 (10)
    • Go (2)
    • 클라우드 (54)
      • DevOps (4)
      • Kubernetes(쿠버네티스) (33)
      • AWS (6)
      • CKA (8)
    • 리눅스(Linux) (18)
      • 컨테이너(Container) (8)
    • Front (22)
      • JavaScript (2)
      • React (20)
    • Python (21)
      • Python 웹 크롤링 (11)
      • Django (7)
      • MachineLearning (3)
    • 데이터베이스 (6)
      • MariaDB (2)
      • MongoDB (4)
    • C언어 (5)
    • Trouble Shooting (2)
    • 네트워크 (8)
      • CCNA (5)
    • 보안 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • replace
  • Patch
  • kubernetes
  • 18
  • 15
  • apply
  • edit

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
happyso

study with happyso

[python] 백준 > DFS > 구슬찾기(2617)
알고리즘/알고리즘 문제

[python] 백준 > DFS > 구슬찾기(2617)

2021. 2. 15. 00:43

[문제]

모양은 같으나, 무게가 모두 다른 N개의 구슬이 있다. N은 홀수이며, 구슬에는 번호가 1,2,...,N으로 붙어 있다. 이 구슬 중에서 무게가 전체의 중간인 (무게 순서로 (N+1)/2번째) 구슬을 찾기 위해서 아래와 같은 일을 하려 한다.

우리에게 주어진 것은 양팔 저울이다. 한 쌍의 구슬을 골라서 양팔 저울의 양쪽에 하나씩 올려 보면 어느 쪽이 무거운가를 알 수 있다. 이렇게 M개의 쌍을 골라서 각각 양팔 저울에 올려서 어느 것이 무거운가를 모두 알아냈다. 이 결과를 이용하여 무게가 중간이 될 가능성이 전혀 없는 구슬들은 먼저 제외한다.

예를 들어, N=5이고, M=4 쌍의 구슬에 대해서 어느 쪽이 무거운가를 알아낸 결과가 아래에 있다.

  1. 구슬 2번이 구슬 1번보다 무겁다.
  2. 구슬 4번이 구슬 3번보다 무겁다.
  3. 구슬 5번이 구슬 1번보다 무겁다.
  4. 구슬 4번이 구슬 2번보다 무겁다.

위와 같이 네 개의 결과만을 알고 있으면, 무게가 중간인 구슬을 정확하게 찾을 수는 없지만, 1번 구슬과 4번 구슬은 무게가 중간인 구슬이 절대 될 수 없다는 것은 확실히 알 수 있다. 1번 구슬보다 무거운 것이 2, 4, 5번 구슬이고, 4번 보다 가벼운 것이 1, 2, 3번이다. 따라서 답은 2개이다.

M 개의 쌍에 대한 결과를 보고 무게가 중간인 구슬이 될 수 없는 구슬의 개수를 구하는 프로그램을 작성하시오.

입력

첫 줄은 구슬의 개수를 나타내는 정수 N(1 ≤ N ≤ 99)과 저울에 올려 본 쌍의 개수 M(1 ≤ M ≤ N(N-1)/2)이 주어진다. 그 다음 M 개의 줄은 각 줄마다 두 개의 구슬 번호가 주어지는데, 앞 번호의 구슬이 뒤 번호의 구슬보다 무겁다는 것을 뜻한다.

출력

첫 줄에 무게가 중간이 절대로 될 수 없는 구슬의 수를 출력 한다.

 

[풀이]

from collections import defaultdict

def dfs(node, weight):
    global cnt
    visited[node] = True
    for n in weight[node]:
        if not visited[n]:
            cnt += 1
            dfs(n, weight)
    return cnt

if __name__ == '__main__':    
    N, M = map(int, input().split())
    arr = [list(map(int, input().split())) for _ in range(M)]
    result = 0

    light = defaultdict(list)
    heavy = defaultdict(list)

    for x, y in arr:
        heavy[x].append(y)
        light[y].append(x)

    for i in range(1, N+1):
        visited = [False]*(N+1)
        cnt = 0
        if dfs(i, heavy) >= (N+1)//2:
            result += 1
        cnt = 0
        if dfs(i, light) >= (N+1)//2:
            result += 1
    print(result)

 

  • 처음에 문제 이해하기가 너무 어려웠다.
  • 어떤 값이 다른 값보다 크거나 작은 갯수가 전체갯수의 반개 이상이라면 그것은 절때 중간 값이 될 수 없다.
  • 그래서 일단 현재 값을 기준으로 연결돼있는 노드 갯수를 구하고 그 갯수가 (N+1)//2개 이상이면 result에 1을 더해준뒤 값을 구한다.
  • defaultdict를 사용하니 굉장히 편리했다.
  • 따로 N+1개의 리스트를 만들어 넣어줄 필요 없이 노드 값을 key값으로 해당 노드에 연결돼있는 노드값을 value값으로 넣어준 뒤에 관리하였다.
  • 그리고 큰 값과 작은값 두개를 구해야 하는데 그럴려면 노드 방향을 하나는 똑바로 하나는 반대로 한 뒤에 비교해야 했다.(이부분을 놓쳤다)

[다른 사람의 풀이]

import sys
from collections import deque
input = sys.stdin.readline
n, m = map(int, input().split())
graph = {i:[] for i in range(1,n+1)}
for _ in range(m):
    a, b = map(int, input().split())
    graph[a].append((b,True)) 
    graph[b].append((a, False))  
def bfs(start):
    dq = deque()
    check_greater, check_less = set(), set()
    dq.append((start, False))
    dq.append((start, True))
    while dq:
        node, s = dq.popleft()
        if len(check_greater) > n // 2 or len(check_less) > n // 2:
            return 1
        for n_n, n_s in graph[node]:
            if (n_n not in check_greater) and (n_n not in check_less):
                if (not s) and (not n_s):
                    dq.append((n_n, n_s))
                    check_greater.add(n_n)
                elif s and n_s:
                    dq.append((n_n, n_s))
                    check_less.add(n_n)
    return 0
count = 0
for i in range(1, n+1):
    count += bfs(i)
print(count)
  • graph에 넣어줄 때 기준 값보다 큰지 작은지 True, False로 구분해서 넣어줬다.
  • check를 두가지로 만들어서 현재 구슬보다 큰지 작은지 구분해서 방문 체크했다.

'알고리즘 > 알고리즘 문제' 카테고리의 다른 글

[python] 백준 > 부루트포스 > 체스판 다시 칠하기(1018)  (0) 2021.02.16
[python] 백준 > 다익스트라 > 알고스팟(1261)  (0) 2021.02.15
[python] 백준 > DFS/BFS > 음식물 피하기(1743)  (0) 2021.02.12
[python] 백준 > BFS > Puyo Puyo(11559)  (0) 2021.02.11
[python] 백준 > DP > 포도주 시식  (0) 2021.02.09
    '알고리즘/알고리즘 문제' 카테고리의 다른 글
    • [python] 백준 > 부루트포스 > 체스판 다시 칠하기(1018)
    • [python] 백준 > 다익스트라 > 알고스팟(1261)
    • [python] 백준 > DFS/BFS > 음식물 피하기(1743)
    • [python] 백준 > BFS > Puyo Puyo(11559)
    happyso
    happyso

    티스토리툴바