어떤 상어는 저녁식사로 서로를 먹는다. 모든 상어는 자신과 다른 상어의 크기, 속도, 지능을 수치로 나타낸 것을 알고 있다. 만약, 상어 A의 크기, 속도, 지능이 상어 B의 크기, 속도, 지능보다 크거나 같다면 상어 A는 상어 B를 먹을 수 있다. 그러나, 상어들의 왕 김재홍은 상어들이 많이 없어지는 것을 방지하기 위해서 한 상어가 최대 두 개의 상어만 먹을 수 있게 했다. 상어들은 김재홍의 말을 모두 듣는다.
한 상어가 다른 상어를 잡아먹는 동안 나머지 상어들은 상어를 잡아먹을 수 없으며, 이미 잡아먹힌 상어는 다른 상어들을 잡아먹을 수 없다.
N마리 상어의 크기, 속도, 지능이 주어졌을 때, 살아남을 수 있는 상어 수의 최솟값을 구하시오.
이분 매칭 특집. 어제도 그저께도 풀었던 문제와 본질적으로는 동일하다. 이미 잡아먹힌 상어는 다른 상어들을 잡아먹을 수 없다는 함정에 빠지지 말자. 모든 매칭을 종료하면, 위상 순으로 잡아먹을 때 최대 상어가 잡아먹히게 되고 최소 상어가 살아남는다.
문제는 사이클 발생 여부이다. 크기, 속도, 지능 수치가 서로 같은 둘 이상의 상어는 사이클을 형성하고, 매칭이 올바르게 이루어지지 않게 된다. 즉 이 경우에는 강제로 두 상어간의 위상을 정해 주어야 한다. 이를 테면 인덱스 정보 등으로 모든 상어들이 사이클을 형성하지 않도록 하는 방법이 있겠다.
풀이 코드
N = int(input())
sharks = [list(map(int, input().split())) for _ inrange(N)]
eatable_list = [list() for _ inrange(N)]
eaten = [-1]*N
visited = [False]*N
for i inrange(N-1) :
ia, ib, ic = sharks[i]
for j inrange(i+1, N) :
ja, jb, jc = sharks[j]
if ia >= ja and ib >= jb and ic >= jc :
eatable_list[i].append(j)
elif ia <= ja and ib <= jb and ic <= jc :
eatable_list[j].append(i)
defdfs(shark) :
for other in eatable_list[shark] :
if eaten[other] == -1 :
eaten[other] = shark
returnTruefor other in eatable_list[shark] :
if visited[other] :
continue
visited[other] = Trueif dfs(eaten[other]) :
visited[other] = False
eaten[other] = shark
returnTruereturnFalse
ans = 0for i inrange(N) :
if dfs(i) :
ans += 1for i inrange(N) :
if dfs(i) :
ans += 1print(N - ans)