알고리즘/문제풀이

[Python] 백준 14676 영우는 사기꾼

정찡이 2021. 9. 18. 14:43
728x90

1. 문제 링크

https://www.acmicpc.net/problem/14676

 

14676번: 영우는 사기꾼?

프로그램의 입력은 표준 입력으로 받는다. 입력의 첫 줄에는 건물 종류의 개수 N, 건물 사이 관계의 개수 M, 영우의 게임 정보의 개수 K가 주어진다.(1 ≤ N, M, K ≤ 100,000) 다음 줄부터 M줄에 걸쳐

www.acmicpc.net

2. 문제 요약


3. 아이디어 정리

1. 우선 위상 정렬을 하기 위해 진입 차수를 아래와 같이 저장한다.

2. 건설을 하는 경우

  • 진입 차수가 0이 아니면 치트키 사용
  • 0이고 처음 건물을 지은 경우는 다음 연결 관계를 가진 진입 차수를 -1 하여 건물을 짓도록 한다.

3. 파괴하는 경우

  • 지은 건물이 지금까지 없는 경우 치트키 사용
  • 그 외의 경우 파괴된 건물이 마지막이면 다음 연결 관계를 가진 진입 차수를 + 1 하여 건물을 못 짓게 한다.

4. 문제 풀이

4-1. 내 풀이

import sys

# 건물 종류, 건물 사이 관계, 게임 정보의 개수
n, m, k = map(int, sys.stdin.readline().split())

indegree = [0] * (n + 1)            # 진입차수 
graph = [[] for i in range(n + 1)]  # 연결관계 저장 
now = [0] * (n + 1)                 # 현재 지은 건물 수 
lier_flag = False                   # 영우의 치트키 여부 

for _ in range(m):
    # x를 건설해야 y건설 가능
    x, y = map(int, sys.stdin.readline().split())
    graph[x].append(y)
    indegree[y] += 1    # 진입 차수 > 해당 건물 지어지기 전 기어야할 건물 수 

for _ in range(k):
    # 1:건설, 2 파괴
    n, a = map(int, sys.stdin.readline().split())
    if n == 1:
        if indegree[a] != 0:  # 진입차수 0 아니면 건설 x
            lier_flag = True
            break
        else:
            now[a] += 1   # 지은 건물 수 증가
            if now[a] == 1:   # 처음 건설한 경우 진입차수 -1 를 하여 내 다음 번호가 건물 건설이 가능하도록함
                for next in graph[a]:
                    indegree[next] -= 1

    else:
        if now[a] <= 0:   # 지은 건물이 없는 경우 거짓말
            lier_flag = True
            break
        else:
            now[a] -= 1
            if now[a] == 0:      # 마지막 건물이 파괴된 경우, + 1를 해서 건설을 못하게 진입 차수 증가 
                for next in graph[a]:
                    indegree[next] += 1

if lier_flag:
    print("Lier!")
else:
    print("King-God-Emperor")

 


5. 결론

  • 변형된 위상 정렬 문제이다.
반응형