[ 카카오 / Python ] 2024 KAKAO WINTER INTERNSHIP - 도넛과 막대 그래프

박제현·2024년 3월 15일
0

코딩테스트

목록 보기
76/101

문제 설명

도넛 모양 그래프, 막대 모양 그래프, 8자 모양 그래프들이 있습니다. 이 그래프들은 1개 이상의 정점과, 정점들을 연결하는 단방향 간선으로 이루어져 있습니다.

  • 크기가 n인 도넛 모양 그래프는 n개의 정점과 n개의 간선이 있습니다. 도넛 모양 그래프의 아무 한 정점에서 출발해 이용한 적 없는 간선을 계속 따라가면 나머지 n-1개의 정점들을 한 번씩 방문한 뒤 원래 출발했던 정점으로 돌아오게 됩니다. 도넛 모양 그래프의 형태는 다음과 같습니다.

  • 크기가 n인 막대 모양 그래프는 n개의 정점과 n-1개의 간선이 있습니다. 막대 모양 그래프는 임의의 한 정점에서 출발해 간선을 계속 따라가면 나머지 n-1개의 정점을 한 번씩 방문하게 되는 정점이 단 하나 존재합니다. 막대 모양 그래프의 형태는 다음과 같습니다.
  • 크기가 n인 8자 모양 그래프는 2n+1개의 정점과 2n+2개의 간선이 있습니다. 8자 모양 그래프는 크기가 동일한 2개의 도넛 모양 그래프에서 정점을 하나씩 골라 결합시킨 형태의 그래프입니다. 8자 모양 그래프의 형태는 다음과 같습니다.

도넛 모양 그래프, 막대 모양 그래프, 8자 모양 그래프가 여러 개 있습니다. 이 그래프들과 무관한 정점을 하나 생성한 뒤, 각 도넛 모양 그래프, 막대 모양 그래프, 8자 모양 그래프의 임의의 정점 하나로 향하는 간선들을 연결했습니다.
그 후 각 정점에 서로 다른 번호를 매겼습니다.
이때 당신은 그래프의 간선 정보가 주어지면 생성한 정점의 번호와 정점을 생성하기 전 도넛 모양 그래프의 수, 막대 모양 그래프의 수, 8자 모양 그래프의 수를 구해야 합니다.

그래프의 간선 정보를 담은 2차원 정수 배열 edges가 매개변수로 주어집니다. 이때, 생성한 정점의 번호, 도넛 모양 그래프의 수, 막대 모양 그래프의 수, 8자 모양 그래프의 수를 순서대로 1차원 정수 배열에 담아 return 하도록 solution 함수를 완성해 주세요.

제한사항

  • 1 ≤ edges의 길이 ≤ 1,000,000
    • edges의 원소는 [a,b] 형태이며, a번 정점에서 b번 정점으로 향하는 간선이 있다는 것을 나타냅니다.
    • 1 ≤ a, b ≤ 1,000,000
  • 문제의 조건에 맞는 그래프가 주어집니다.
  • 도넛 모양 그래프, 막대 모양 그래프, 8자 모양 그래프의 수의 합은 2이상입니다.

입출력 예

edgesresult
[[2, 3], [4, 3], [1, 1], [2, 1]][2, 1, 1, 0]
[[4, 11], [1, 12], [8, 3], [12, 7], [4, 2], [7, 11], [4, 8], [9, 6], [10, 11], [6, 10], [3, 5], [11, 1], [5, 3], [11, 9], [3, 8]][4, 0, 1, 2]

풀이

도넛, 막대, 8자 모양 그래프의 특징을 찾고 문제를 풀어야 한다.

도넛은 하나의 출력이 있고, 하나의 입력이 있다.
A → B → C → A
이 예에서 A 는 B로 가는 출력 하나, C로 부터 들어오는 입력 하나.
B는 C로 가는 출력 하나, A로 부터 들어오는 입력 하나.
C는 A로 가는 출력 하나, B로 부터 들어오는 입력 하나.

막대는 시작 노드는 입력이 없고, 출력만 한개 존재하며, 끝 노드에서는 입력만 한개 존재하고, 출력은 없다.
A → B → C
이 예에서 A는 B로 가는 출력 하나, B는 C로 가는 출력 하나, C는 입력만 존재한다.

8자 모양은 허리 노드는 입력이 2개, 출력이 2개라는 점이 특징이다.
A → B → A → C
이 예에서 A가 허리 노드에 해당된다.

우선, 각 도형의 특징은 찾았으니 이제 임의로 그린 점을 찾아야 한다.
이 임의의 점은 위의 도형에 포함되어 있지 않으므로, 입력이 없다.

그리고 각 도형은 최소 두개 이상 존재한다고 하므로, 임의의 점은 최소 두개 이상의 점들과 연결되어 있다는 말이다.

그러므로 임의의 점 조건은 출력은 2개 이상이며, 입력은 없다는 점이다.

임의의 점은 모든 도형들과 연결되어 있으므로, 임의의 점들과 연결된 도형이 무엇인지 체크하면 문제를 풀 수 있다.

임의의 점과 연결된 점을 탐색 시작점으로 잡고, 탐색을 수행하며 해당 노드들의 조건이 도넛, 막대, 8자 모양에 해당하는 지 확인한다.

해당 풀이법을 참고하였다.

코드

from collections import defaultdict, deque


def solution(edges):
    MAX_LEN = 1_000_001

    answer = [0, 0, 0, 0]

    go = [[] for _ in range(MAX_LEN)]
    take = [[] for _ in range(MAX_LEN)]

    for g, t in edges:
        go[g].append(t)
        take[t].append(g)

    start = 0

    for i in range(MAX_LEN):
        if len(go[i]) >= 2 and len(take[i]) == 0:
            start = i
            break

    answer = [start, 0, 0, 0]

    visited = [False] * MAX_LEN

    def bfs(i):
        q = deque([i])
        visited[i] = True

        while q:
            node = q.popleft()

            if not go[node]:
                answer[2] += 1
                return
            if len(go[node]) == 2 and len(take[node]) == 2:
                answer[3] += 1
                return
            for next_node in go[node]:
                if not visited[next_node]:
                    visited[next_node] = True
                    q.append(next_node)

        answer[1] += 1

    for node in go[start]:
        take[node].remove(start)
        bfs(node)

    print(answer)
    return answer


solution([[2, 3], [4, 3], [1, 1], [2, 1]])

profile
닷넷 새싹

0개의 댓글