주어진 정점에서 최단경로로 이동시 가장 먼 정점들의 갯수를 구하는 문제로서, 노드와 엣지 & 가중치가 있기 때문에 다익스트라 알고리즘을 적용해야 하는 문제이다.
입력값은 정점들의 갯수와 [[3, 6], [4, 3], [3, 2], [1, 3], [1, 2], [2, 4], [5, 2]] 과 같이 두 정점간 연결 상태를 제시한다.
해결단계는 크게 3단계로 나누었다.
- 데이터 구조 마련
- 알고리즘 적용하여 각 정점별 최단거리 추출
- 최대값의 갯수 추출 (해)
각 단계에 대한 설명
- 데이터 구조 마련
- arrange 함수에서 입력값을 알고리즘 적용에 용이하도록 구조를 짬
- newEdge
- 알고리즘이 알아들을 수 있는 데이터 구조 (dictionary 선언)
- for _from, _to in edge
- 입력값 내에서 쌍으로 되어있는 엣지 두개를 추출한다
- {시작정점 : [끝정점 : 가중치]} 형태가 되도록 데이터를 채워간다
- 양방향 노드이므로 정점의 순서를 바꿔서 채우기도 포함
def arrange(edge):
newEdge = {}
for _from, _to in edge:
empty = [_to, 1]
if not _from in newEdge:
newEdge[_from] = []
newEdge[_from].append(empty)
empty = [_from, 1]
if not _to in newEdge:
newEdge[_to] = []
newEdge[_to].append(empty)
return newEdge
- 다익스트라 알고리즘
import heapq
def dijkstra(cnt, edge):
# 최단거리 검색 시간을 O(N * log N) 수준으로 줄이기 위해 우선순위 큐를 이용할 것이고, 이를 위한 컨테이너
arc = []
# 시작정점에서 목표정점까지의 거리(가중치)를 담을 리스트 선언
# 리스트의 인덱스 번호를 정점 번호(이름)로 간주할 것이므로 엣지 갯수 + 1 의 크기로 선언
# distances[0] 은 0번 정점까지의 거리를 의미하는데, 문제에서 0번 정점은 존재하지 않는다.
# 그러므로 유효한 값은 distances[1] ~ distances[정점갯수] 가 된다.
# 우리는 이 distances 값을 구하는 게 목표이다.
# 초기에는 각 정점까지의 거리를 알 수 없으므로 무한대 거리로 선언 - float('inf')
# distances[1] = 0 은 시작점(1번 정점) 에서 1번 정점간 거리가 0이라는 의미이고,
# distances[2] = 1 는 시작점에서 2번 정점으로 가기까지의 거리가 1 이라는 의미이다.
distances = [float('inf') for i in range(cnt+1)]
# 문제에서 시작점은 1로 고정이므로 distances[1] = 0 이 된다 (자기 자신과의 거리는 0 으로 설정)
distances[1] = 0
# 첫번째 인자는 넣을 데이터, 두번째 인자는 넣을 아이템인데, 만약 이값이 튜플이라면 튜플의 첫번째 요소를 우선순위 값으로 간주한다.
# 이를 응용해 최소힙만 지원하는 heapq를 최대힙으로 바꿀수도 있다. (첫번째 인자에 -를 붙이면 됨)
# 튜플의 첫번째 요소는 두번쨰 요소인 정점까지의 거리, 두번째 요소는 정점으로 설정하면
# 우선순위인 거리에 의해 자동정렬되어 최단거리 검색 시간을 선형리스트를 쓰는 것에 비해 줄일 수 있다
# 선형 리스트 O = N^2, 우선순위 큐 O = N * logN
heapq.heappush(arc, (0, 1))
# 큐에 더이상 값이 없을때까지 반복
while arc:
# 힙에서 뽑아낸 값은 튜플로서 (정점, 거리)
current, distance = heapq.heappop(arc)
# 만약 이미 저장된 정점까지의 거리보다 새로 뽑은 값이 크면 이미 최단 경로가 저장되어 있다는 의미이므로 넘긴다.
if distances[current] < distance:
continue
# 위 arrange 함수에서 각 정점이 어떤 정점들과 연결되어 있는지 정리했으므로
# 현재 정점과 연결되어있는 모든 정점의 거리를 추출한다.
for _next, _nextDist in edge[current]:
# _next : 인접노드
# _nextDist : 인접노드까지의 거리
# 선택된 노드를 인접 노드로 거쳐서 가는 거리
_nextDist += distance
# 거쳐서 가는 거리가, 기존 거리보다 작으면 (짧으면) 최적 경로로 간주하고 비용 교체
if _nextDist < distances[_next]:
distances[_next] = _nextDist
heapq.heappush(arc, (_nextDist, _next))
# 유효한 값은 distances[1] 부터 이므로 짜른다
return distances[1:]
- 최대값의 갯수 추출
def solution(n, edge):
answer = 0
distances = dijkstra(n, arrange(edge))
maxDist = max(distances)
for dist in distances:
if dist == maxDist:
answer += 1
return answer
'Python > 프로그래머스 코딩테스트 연습' 카테고리의 다른 글
완전탐색 / 모의고사 (0) | 2020.09.15 |
---|---|
정렬 / H-Index (0) | 2020.09.10 |
힙 / 더 맵게 (0) | 2020.09.10 |
스택&큐 / 기능개발 (0) | 2020.09.10 |
스택&큐 / 주식가격 (0) | 2020.09.10 |