https://www.acmicpc.net/problem/2458
2458번: 키 순서
1번부터 N번까지 번호가 붙여져 있는 학생들에 대하여 두 학생끼리 키를 비교한 결과의 일부가 주어져 있다. 단, N명의 학생들의 키는 모두 다르다고 가정한다. 예를 들어, 6명의 학생들에 대하여
www.acmicpc.net
1. 풀이
전형적인 플루이드 마셜 구현 문제이다. 플루이드 마셜은 모든 노드에대한 모든 노드의 최단 거리를 구하는 알고리즘이다.
특정한 학생의 키순서를 알기 위해선 자신보다 몇 명이 큰지 그리고 몇명이 작은지 전체 학생 수에 대해서 알아야한다.
예를 들어 전체 학급 구성이 8명인 반에서 학생 A가 전체 반에서 4번째로 크다고 가정해보자.
이 학생이 4번째로 큰 학생임을 알기 위해선 위로 3명 아래로 4명이 있음을 알아야 본인이 4번째로 큰지 알 수 있다.
학생을 노드로 표현하고 대소관계를 간선으로 표현한 방향 그래프에서 학생 A보다 큰 학생수는 학생 A에서 도달할 수 있는 노드의 수와 동일하다.
즉 학생 A와 연결되어 있는 노드의 수를 세면 된다. 이를 위해서 인접 행렬을 통해 비교되어 있는 간선을 1로 표시하고
플루이드 마셜을 돌면서 A-> B , B-> C 와 같은 두개의 연결관계가 있으면 adj[A][C] 에 1을 표시해준다.
마지막으로 인접 행렬을 돌면서 대소관계가 있는 노드들에 대해 횟수를 더해주고 이 값이 전체 학생수 N보다 1이 작은 수이면 해당 노드는 자신이 학급에서 얼마나 큰지 알 수 있게 된다.
N, M = map(int, input().split())
adj = [[0 for i in range(N)] for j in range(N)]
for i in range(M):
p, c = map(int, input().split())
adj[p-1][c-1] =1
for i in range(N):
for row in range(N):
for col in range(N):
if adj[row][i] +adj[i][col] ==2:
adj[row][col] =1
cnt =[0 for i in range(N)]
for i in range(N):
for j in range(N):
if adj[i][j] ==1:
cnt[i] +=1
cnt[j] +=1
print(cnt.count(N-1))
2. 다른 풀이
개념은 동일하게 자신보다 큰 값과 작은 값을 세는 방식
DFS를 통해 시간 복잡도를 줄였다.
import sys
input=sys.stdin.readline
sys.setrecursionlimit(10**9)
n,m=map(int,input().split())
taller=[set() for _ in range(n)]
shorter=[set() for _ in range(n)]
e=[[] for _ in range(n)] #자기보다 큰 노드들이 적혀있는 인접리스트
e_inv=[[] for _ in range(n)] #자기보다 작은 노드들이 적혀있는 인접리스트
for _ in range(m):
a,b=map(int,input().split()) #입력을 받으면서
e[a-1].append(b-1) #큰 관계
e_inv[b-1].append(a-1) #작은 관계 각각 입력
v=[0 for i in range(n)] # 큰 값 세기
v_inv=[0 for i in range(n)] # 작은 값 세기
def find_taller(i): #DFS로 자기보다 큰 관계 있는 학생수를 센다
if v[i]: return taller[i]
v[i]=1
for j in e[i]: #인접리스트에서
taller[i].add(j)
taller[i]|=find_taller(j)
return taller[i]
def find_shorter(i):#DFS로 자기보다 작은 관계 있는 학생수를 센다
if v_inv[i]: return shorter[i]
v_inv[i]=1
for j in e_inv[i]:
shorter[i].add(j)
shorter[i]|=find_shorter(j)
return shorter[i]
c=0
for i in range(n):
find_taller(i)
find_shorter(i)
if len(taller[i])+len(shorter[i])==n-1: c+=1
print(c)
'Algorithm > 백준 온라인 저지(BOJ)' 카테고리의 다른 글
09/03 미확인 도착지 BOJ 9370 (0) | 2020.09.03 |
---|---|
09/02 교환 BOJ 1039 파이썬 (0) | 2020.09.02 |
08/30 카드게임 BOJ 10835 파이썬 (0) | 2020.08.30 |
08/28 아기상어 BOJ 16236 파이썬 (0) | 2020.08.28 |
08/27 퇴사 BOJ 14501 파이썬 (0) | 2020.08.27 |