
메모리: 115272 KB, 시간: 124 ms
깊이 우선 탐색, 플로이드–워셜, 그래프 이론, 그래프 탐색
모양은 같으나, 무게가 모두 다른 N개의 구슬이 있다. N은 홀수이며, 구슬에는 번호가 1,2,...,N으로 붙어 있다. 이 구슬 중에서 무게가 전체의 중간인 (무게 순서로 (N+1)/2번째) 구슬을 찾기 위해서 아래와 같은 일을 하려 한다.
우리에게 주어진 것은 양팔 저울이다. 한 쌍의 구슬을 골라서 양팔 저울의 양쪽에 하나씩 올려 보면 어느 쪽이 무거운가를 알 수 있다. 이렇게 M개의 쌍을 골라서 각각 양팔 저울에 올려서 어느 것이 무거운가를 모두 알아냈다. 이 결과를 이용하여 무게가 중간이 될 가능성이 전혀 없는 구슬들은 먼저 제외한다.
예를 들어, N=5이고, M=4 쌍의 구슬에 대해서 어느 쪽이 무거운가를 알아낸 결과가 아래에 있다.
위와 같이 네 개의 결과만을 알고 있으면, 무게가 중간인 구슬을 정확하게 찾을 수는 없지만, 1번 구슬과 4번 구슬은 무게가 중간인 구슬이 절대 될 수 없다는 것은 확실히 알 수 있다. 1번 구슬보다 무거운 것이 2, 4, 5번 구슬이고, 4번 보다 가벼운 것이 1, 2, 3번이다. 따라서 답은 2개이다.
M 개의 쌍에 대한 결과를 보고 무게가 중간인 구슬이 될 수 없는 구슬의 개수를 구하는 프로그램을 작성하시오.
첫 줄은 구슬의 개수를 나타내는 정수 N(1 ≤ N ≤ 99)과 저울에 올려 본 쌍의 개수 M(1 ≤ M ≤ N(N-1)/2)이 주어진다. 그 다음 M 개의 줄은 각 줄마다 두 개의 구슬 번호가 주어지는데, 앞 번호의 구슬이 뒤 번호의 구슬보다 무겁다는 것을 뜻한다.
첫 줄에 무게가 중간이 절대로 될 수 없는 구슬의 수를 출력 한다.
인접리스트에 a를 기준으로 b를 저장하는것은 a가 b보다 무겁다는 의미.
인접리스트에 b를 기준으로 a를 저장하는것은 b보다 a가 무겁다는 의미.
두가지 배열을 같은 dfs 함수에 적용하면, 각각 최소가되서 제외되는것, 최대가 되서 제외되는것을 각각 찾아낼 수 있다.
플로이드 워셜 알고리즘을 적용한 문제로 나와있다. 플로이드 워셜로 풀이가 가능하다는건? dfs로 풀이가 가능하다는것! 이 문제를 풀이할때, 사실 트러블 슈팅은 없었다. 트러블이 안난체로, 거의 한큐에 문제풀이에 성공했다. 알고리즘 자체는 간단했던것 같다.
난 dfs에 check라는 리스트를 만들어서, dfs에서 탐색하는 모든 노드들을 저장해줬는데, 이렇게하면 start에 입력된 값보다 무겁거나 가벼운것들을 모두 모아놓을 수있다. 그뒤 check 리스트를 리턴해주면 끝!
def dfs(graph, start, visit):
stack = []
stack.append((start))
check = []
while stack:
value= stack.pop()
if visit[value] == 0:
visit[value] = 1
for node in graph[value]:
if visit[node] == 0:
visit[node] = 1
check.append(node)
stack.append(node)
return check
나온 리턴값을 가공해 문제에 알맞은 출력값으로 변환해 주면된다. 나같은 경우엔 최대, 최소를 모든 정점에 대해서 찾아준뒤, 그 배열의 개수가 (n+1)/2 를 넘을때 카운트 해주는 방식으로 풀었다.
#https://www.acmicpc.net/problem/2617
#구슬 찾기
#2617
import sys
input = sys.stdin.readline
n, m = map(int, input().split())
max_graph = [[] for _ in range(n+1)]
min_graph = [[] for _ in range(n+1)]
for _ in range(m):
a , b = map(int, input().split())
max_graph[a].append(b)
min_graph[b].append(a)
# print(max_graph)
# print(min_graph)
# visit = [0] * (n+1)
count = [0] * (n+1)
def dfs(graph, start, visit):
stack = []
stack.append((start))
check = []
while stack:
value= stack.pop()
if visit[value] == 0:
visit[value] = 1
for node in graph[value]:
if visit[node] == 0:
visit[node] = 1
check.append(node)
stack.append(node)
# print(check)
# print(stack)
return check
min_count = 0
max_count = 0
for i in range(n):
visit = [0] * (n+1)
result = dfs(min_graph, i+1, visit)
# print(len(result))
if len(result) >= (n+1)/2:
min_count +=1
# print(min_count)
for i in range(n):
visit = [0] * (n+1)
result = dfs(max_graph, i+1, visit)
# print(len(result))
if len(result) >= (n+1)/2:
max_count +=1
# print(max_count)
answer = min_count + max_count
print(answer)