[Python - DFS] 9466 텀 프로젝트

2022. 8. 28. 18:58· Algorithm/Graph
목차
  1. 👨‍🏫 접근
  2. 👨‍🏫 문제 풀이
  3. 📄 전체 코드
  4. 📄 준비
  5. 📄 풀이

📌 문제

이번 가을학기에 '문제 해결' 강의를 신청한 학생들은 텀 프로젝트를 수행해야 한다. 프로젝트 팀원 수에는 제한이 없다. 심지어 모든 학생들이 동일한 팀의 팀원인 경우와 같이 한 팀만 있을 수도 있다. 프로젝트 팀을 구성하기 위해, 모든 학생들은 프로젝트를 함께하고 싶은 학생을 선택해야 한다. (단, 단 한 명만 선택할 수 있다.) 혼자 하고 싶어하는 학생은 자기 자신을 선택하는 것도 가능하다.

학생들이(s1, s2, ..., sr)이라 할 때, r=1이고 s1이 s1을 선택하는 경우나, s1이 s2를 선택하고, s2가 s3를 선택하고,..., sr-1이 sr을 선택하고, sr이 s1을 선택하는 경우에만 한 팀이 될 수 있다.

예를 들어, 한 반에 7명의 학생이 있다고 하자. 학생들을 1번부터 7번으로 표현할 때, 선택의 결과는 다음과 같다.

1234567

3 1 3 7 3 4 6

위의 결과를 통해 (3)과 (4, 7, 6)이 팀을 이룰 수 있다. 1, 2, 5는 어느 팀에도 속하지 않는다.

주어진 선택의 결과를 보고 어느 프로젝트 팀에도 속하지 않는 학생들의 수를 계산하는 프로그램을 작성하라.

📌 입력

content

📌 출력

content

📌 문제 풀이

👨‍🏫 접근

사이클을 찾는 문제. 사이클은 대개 DFS 등 재귀를 통해서 종종 구현하는 편이다. 이 문제가 어려웠던 점은 사이클을 구현하고 값을 구해도 값을 구하는 과정에서 시간 소요를 최소한으로 해야 했기 때문이다.

시간 초과를 최소화 하기 위해서 방문 처리를 어떻게 완료할 것인지 확실히 작성해야 한다. 이미 탐색하면서 사이클이 확인되었다면, 다음 탐색에서 그 사이클을 다시 분석하여 시간을 다시 소요하는 불필요한 과정을 없앤다.

👨‍🏫 문제 풀이

📄 전체 코드

import sys
sys.setrecursionlimit(10**6)
input = sys.stdin.readline

t = int(input())


def check_team(k):  # k: 현재 노드
    global cnt

    visited[k] = True
    next = member[k]

    if not visited[next]: # 아직 방문하지 않았다면
        check_team(next)

    elif not done[next]:
        j = next
        while j != k:
            cnt += 1
            j = member[j]
        cnt += 1

    done[k] = True # 현재 노드는 완료 처리


for _ in range(t):
    n = int(input())
    member = [0] + list(map(int, input().split()))
    visited = [False] * (n + 1)
    done = [False] * (n + 1)

    cnt = 0

    for i in range(1, n + 1):
        if not visited[i]:
            check_team(i)

    print(n - cnt)

📄 준비

import sys
sys.setrecursionlimit(10**6)
input = sys.stdin.readline

t = int(input())

...

for _ in range(t):
    n = int(input())
    member = [0] + list(map(int, input().split()))
    visited = [False] * (n + 1)
    done = [False] * (n + 1)

    cnt = 0

    for i in range(1, n + 1):
        if not visited[i]:
            check_team(i)

    print(n - cnt)

재귀가 상당히 여러 번 진행되기 때문에 재귀 한계를 늘려준다. 그리고, 방문처리를 한 다음에 값을 구하는 과정이 구현되어야 해서 구현 완료를 했는지에 대한 여부를 담을 테이블도 생성해주도록 했다.

그리고 최종적으로 이미 방문을 했다면 다시 사이클을 확인하지 않도록 하기 위해 방문하지 않았을 때만 알고리즘을 실행하도록 하였다.

📄 풀이

def check_team(k):  # k: 현재 노드
    global cnt

    visited[k] = True
    next = member[k]

    if not visited[next]: # 아직 방문하지 않았다면
        check_team(next)

    elif not done[next]:
        j = next
        while j != k:
            cnt += 1
            j = member[j]
        cnt += 1

    done[k] = True # 현재 노드는 완료 처리

이 과정에서 중요한 것은 다음 방문할 값인 next와 현재의 값인 k이다. 둘을 헷갈리지 않고 잘 구분해서 식을 작성한다. 일단 방문했는지의 여부를 체크한 다음, DFS를 실행한다.

모두 체크한 후에는 이 과정에 대해서 값을 구하는 과정을 실행했는가에 대한 여부를 확인한다. 만약 그렇지 않았다면, 값을 구해준다. 이때 구할 값은 사이클을 만들었을 때, 몇 번의 노드를 거치는지 즉, 몇 명이 팀을 꾸렸는지를 확인하는 것이다. 자신을 포함하여 모든 노드를 체크하면, 본인을 완료 처리 해준다.

📌 총평

거의 하루 종일 풀었다. 아직 구현력이 많이 부족한 듯하다. 보완해야겠다.

 

저작자표시 비영리 (새창열림)

'Algorithm > Graph' 카테고리의 다른 글

[Python - ACM Craft] 1005 ACM Craft  (0) 2022.09.28
[Python - Topology Sort] 2252 줄 세우기  (0) 2022.09.28
[Python] 14502 연구소  (0) 2022.06.22
[Python] 2206 벽 부수고 이동하기  (0) 2022.06.22
  1. 👨‍🏫 접근
  2. 👨‍🏫 문제 풀이
  3. 📄 전체 코드
  4. 📄 준비
  5. 📄 풀이
'Algorithm/Graph' 카테고리의 다른 글
  • [Python - ACM Craft] 1005 ACM Craft
  • [Python - Topology Sort] 2252 줄 세우기
  • [Python] 14502 연구소
  • [Python] 2206 벽 부수고 이동하기
턴태
턴태
import { Dream } from "future";
턴태
턴태의 밑바닥부터 시작하는 de-vlog
턴태
전체
오늘
어제
  • ROOT (187)
    • Node.js (37)
      • ES6 (1)
      • TypeScript (3)
      • Express.js (16)
      • NestJS (16)
      • JS (24)
    • 프론트엔드 (29)
      • CS (5)
    • 백엔드 (1)
      • 검색 (2)
      • Database (1)
    • 기타 툴 (1)
      • git (1)
    • 데브옵스 & 인프라 (19)
      • Kubernetes (15)
      • Docker (2)
      • Monitoring (1)
      • IaC (1)
    • Algorithm (90)
      • Implementation & simulation (5)
      • Math (4)
      • Brute Force (1)
      • String (0)
      • Graph (5)
      • Recursion & Backtracking (19)
      • Divide & Conquer (2)
      • Dynamic Programming (18)
      • Greedy (13)
      • Priority Queue (2)
      • Binary Search (6)
      • Data Structure (7)
      • Shortest Path (5)
      • Minimum Spanning Tree (1)
      • Sorting (1)
      • Prefix Sum (1)
    • Linux (1)
      • Ubuntu (1)
    • Diary (5)
      • Algorithm (1)
      • Conference (1)
      • Retrospective (3)
    • Book (0)
      • Self-Development (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 함수형 프로그래밍
  • 노드
  • 자바스크립트
  • 백트래킹
  • 다이나믹 프로그래밍
  • 네스트
  • 인프런X디프만
  • Kubernetes
  • k8s
  • 파이썬
  • dynamic programming
  • 오먹
  • baekjoon
  • node.js
  • backtracking
  • python
  • 타입스크립트
  • 백준
  • Omuk
  • 인프런
  • nestjs
  • 익스프레스
  • 쿠버네티스
  • Express
  • TypeScript
  • Toy Project
  • GREEDY
  • 디프만
  • N과 M
  • 토이프로젝트

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.1
턴태
[Python - DFS] 9466 텀 프로젝트
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.