Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 백준 2812번
- 큐(Queue)
- DFS(Depth First Search)
- 그리디 알고리즘(Greedy Algorithm)
- 백준 2504번
- 위상 정렬(Topology Sort)
- 분할 정복(Divide and Conquer)
- DFS & BFS
- 백준 2261번
- 스택(Stack)
- BFS(Breadth First Search)
- 백준 10000번
- 백준 17608번
- 백준 9012번
- 위상 정렬(Topological Sort)
- 다익스트라 알고리즘(Dijkstra Algorithm)
- 그래프(Graph)
- 백준 18352번
- 이분 탐색(Binary Search)
- 트리(Tree)
- 알고리즘 개념
- 백준 1707번
- 백준 21606번
- 백준 1948번
- 백준 2493번
- 동적 프로그래밍(Dynamic Programming)
- 플로이드 워셜 알고리즘(Floyd-Warshall Algorithm)
- DFS
- BFS
- 이분 그래프(Bipartite Graph)
Archives
- Today
- Total
Always Be Wise
위상 정렬 : 그래프 수정(백준 1432번) 본문
728x90
▶ 문제 : https://www.acmicpc.net/problem/1432
1432번: 그래프 수정
첫째 줄에 정점의 개수 N이 주어진다. 둘째 줄부터 N개의 줄에는 인접행렬 형식으로 입력이 주어진다. 0은 연결되지 않았음을 의미하고, 1은 연결되었다는 것을 의미한다. N은 50보다 작거나 같은
www.acmicpc.net
##### 문제 #####
# N개의 정점이 있는 그래프가 주어지면, 다음과 같은 방법에 의해서 정점의 번호를 다시 매기고 싶다.
# 모든 그래프의 번호는 1보다 크거나 같고 N보다 작거나 같은 번호를 가져야 한다.
# 만약 V1에서 V2로 연결된 간선이 있다면, V2의 번호는 V1보다 커야 한다.
# 위와 같은 조건을 이용해서 그래프의 번호를 다시 매긴 후에,
# 1번 정점의 새로 고친 번호를 M1, 2번 정점의 새로 고친 번호를 M2, ...,
# N번 정점의 새로 고친 번호를 MN이라고 하면, N개의 수열이 만들어진다.
# 이 수열을 출력하는 프로그램을 작성하시오.
##### 입력 #####
# 첫째 줄에 정점의 개수 N이 주어진다.
# 둘째 줄부터 N개의 줄에는 인접 행렬 형식으로 입력이 주어진다.
# 0은 연결되지 않았음을 의미하고, 1은 연결되었다는 것을 의미한다.
# N은 50보다 작거나 같은 자연수이다.
##### 출력 #####
# 첫째 줄에 수열의 각 원소를 차례대로 공백을 사이에 두고 출력한다.
# 만약 그래프의 번호를 수정할 수 없다면 -1을 출력한다.
# 답이 여러 개일 경우에는 사전 순으로 제일 앞서는 것을 출력한다.
▶ 접근 방법
위상 정렬을 이용하여 해결할 수 있었다.
문제에서 주어진 정점들 간의 대소 관계를 그래프로 표현하였다.
동시에 해당 정보를 바탕으로 정점들의 차수를 구하였다.
이때, 어떤 숫자의 차수가 0이라는 것은 해당 숫자보다 큰 숫자가 없다는 것을 의미한다.
차수가 0인 정점을 시작으로 해당 정점과 인접한 정점들의 차수를 줄여나갔다.
그 과정에서 다시 차수가 0이 되는 숫자가 생기는데 그 숫자가 가장 큰 새로운 숫자가 된다.
이런 방식으로 가장 큰 숫자를 하나 씩 찾아나가면서 정렬을 완성하였다.
▶ 풀이 코드
import sys, heapq
def topology_sort(N):
queue = []
# 정점의 수만큼 아래 과정을 반복한다.
for num in range(1, N + 1):
# 만약 차수가 0이면
if degree[num] == 0:
# 우선 순위 큐에 넣어준다.
# 대신 나중에 사전 순으로 출력하기 위해 숫자를 음수 취한다.
heapq.heappush(queue,-num)
while queue:
now = -heapq.heappop(queue)
# 처음 힙에서 뽑는 것은 그 어느 숫자보다 큰 것이기에
# 해당 숫자를 인덱스로 하는 result 리스트에 전체 개수인 N을 할당한다.
result[now] = N
# 그 다음으로 큰 숫자를 찾기 위해 아래의 과정을 진행한다.
for adj_num in graph[now]:
degree[adj_num] -= 1
if degree[adj_num] == 0:
heapq.heappush(queue,-adj_num)
N -= 1
# 전체 정점의 개수를 입력받는다.
N = int(sys.stdin.readline().rstrip())
# 차수 리스트를 만든다.
degree = [0] * (N + 1)
# 결과를 담을 리스트를 만든다.
result = [0] * (N + 1)
# 정점의 관계를 담을 그래프를 만든다.
graph = [[] for _ in range(N + 1)]
for num in range(1, N + 1):
info = list(map(int,sys.stdin.readline().strip()))
# print(info)
# 입력 받은 값을 graph에 넣어 줄때,
# 정점의 위치 정보가 1부터 시작한다는 것을 고려하여 idx를 변화시키고 차수도 늘려준다.
for idx, value in enumerate(info):
# print(idx, value)
if value == 1:
graph[idx+1].append(num)
degree[num] +=1
print(graph)
print(degree)
topology_sort(N)
if result.count(0) > 1:
print(-1)
else:
print(*result[1:])
▶ 관련 링크
2021.11.20 - [알고리즘] - 위상 정렬(Topological Sort)이란?
2021.11.22 - [알고리즘] - 위상 정렬 : 줄 세우기(백준 2252번)
2021.11.22 - [분류 전체보기] - 위상 정렬 : 장난감 조립(백준 2637번)
'알고리즘 > 백준' 카테고리의 다른 글
BFS : 토마토(백준 7569번) (0) | 2021.11.25 |
---|---|
위상 정렬 : 임계경로(백준 1948번) (0) | 2021.11.24 |
위상 정렬 : 장난감 조립(백준 2637번) (0) | 2021.11.22 |
위상 정렬 : 줄 세우기(백준 2252번) (0) | 2021.11.22 |
DFS : 구슬 찾기(백준 2617번) (0) | 2021.11.22 |
Comments