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
- 덕타이핑
- useLayoutEffect
- useContext
- 프로그래머스
- 프로그래머스 #알고리즘 #자바스크립트
- 스티커
- 다이나믹프로그래밍
- 알고리즘
- 위상정렬
- useRef
- react-beautiful-dnd
- 리코일
- javascript
- 알고리즘 #코딩테스트 #프로그래머스 #자바
- 타입스크립트
- recoil
- usedebugvalue
- 리액트
- Suspense
- 훅
- 드래그앤드롭
- 자바스크립트
- 완전탐색
- 백준
- 알고리즘 #프로그래머스 #코딩테스트 #자바스크립트
- 백준 #알고리즘 #자바스크립트
- React
Archives
- Today
- Total
몽환화
[알고리즘] 위상정렬(Topological Sort) 알아보기 : 자바(Java) 본문
방향을 거스르지 않으면서 순서대로 방문하는 것을 위상정렬이라고 한다.
유향 그래프의 정점들을 변의 방향을 거스르지 않도록 나열하는 것!
순서가 정해져 있는 작업들을 차례대로 수행해야 할 때, 그 순서를 결정해주는 알고리즘이다.
유향 그래프의 구조에 따라 여러개의 종류가 나올 수 있다.
사이클이 존재하면 안된다
=> 위상 정렬이 불가능하다? 사이클이 존재한다
BFS 사용하기
1. 진입 차수가 0인 노드를 모두 큐에 넣는다.
=> 진입 차수가 0 : 해당 정점을 가리키는 정점이 없다. 즉 순서의 시작이 되는 놈이다.
2. 큐에서 진입 차수가 0인 노드를 꺼내 자신과 인접한 노드의 간선을 제거한다.
=> 인접한 노드의 진입 차수를 1씩 감소시킨다.
3. 간선 제거 후 진입 차수가 0이 된 노드가 있다면 큐에 넣는다.
4. 큐가 공백이 될 때 까지 반복한다.
차수 : 정점에 연결된 간선 수
진출차수 : 해당 정점에서 타 정점으로 나가는 간선 수
진입차수 : 타 정점에서 해당 정점으로 들어오는 간선 수
큐에 들어가는 놈들은 진입 차수가 0인 정점들이다.
:: 나를 바라보는 놈들이 더이상 없다면 큐에 들어간다!
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Queue;
import java.util.StringTokenizer;
public class 위상정렬_큐 {
static int N, M;
static class Node{
int vertex;
Node link;
// Node 안에 Node를 파라미터로 갖는다
public Node(int vertex, Node link) {
super();
this.vertex = vertex;
this.link = link;
}
}
static Node[] adjlist; // 인접리스트
static int[] inDegree; // 진입차수
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
// 인접리스트를 노트 클래스로 구현해보자
adjlist = new Node[N + 1];
inDegree = new int[N + 1];
int from, to;
for(int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
from = Integer.parseInt(st.nextToken());
to = Integer.parseInt(st.nextToken());
// 이와 같은 방식으로 from이 to와 연결되게 한다.
adjlist[from] = new Node(to, adjlist[from]);
// 진입차수 증가시키기
inDegree[to]++;
}
ArrayList<Integer> list = topologySort();
if(list.size() == N) {
for(Integer vertex : list) {
System.out.print(vertex + " ");
}
System.out.println();
} else {
System.out.println("cycle");
}
}
static ArrayList<Integer> topologySort(){
// 반환할 어레이리스트
// 만일 사이클이 형성되지 않는 간선들이라면 큐를 다 뽑았을 때 N개라는 보장을 할 수 없다.
// 그러니 N크기의 배열이 아닌 어레이리스트를 사용하자.
ArrayList<Integer> orderList = new ArrayList<>();
// 진입차수가 0이 된 노드들을 집어넣어줄 큐
Queue<Integer> queue = new ArrayDeque<Integer>();
for(int i = 1; i <= N; i++) {
// 진입차수가 0인 애들 일단 큐에 넣기
if(inDegree[i] == 0) queue.offer(i);
}
// 큐가 텅텅 빌 때 까지 반복하자
while(!queue.isEmpty()) {
int cur = queue.poll();
// 일단 뽑았다면 뽑은거니 반환할 어레이리스트에 집어넣고
orderList.add(cur);
// 현재 뽑힌 정점의 간선을 탐색하자
// Node라는게 어쩄든 int랑 Node를 파라미터로 갖는 애니까
// tmp.link 하면 Node가 나오는거고
for(Node tmp = adjlist[cur]; tmp != null; tmp = tmp.link) {
if(--inDegree[tmp.vertex]==0) {
queue.offer(tmp.vertex);
}
}
}
return orderList;
}
}
'알고리즘' 카테고리의 다른 글
[백준] 1107 리모컨 : 자바스크립트(node.js) (0) | 2024.05.10 |
---|---|
[백준] 9465 스티커 : 자바스크립트(node.js) (0) | 2024.05.09 |
[백준] 1347 미로 만들기 : 자바스크립트(node.js) (1) | 2024.05.03 |
[백준] 2011 암호코드 : 자바스크립트(node.js) (0) | 2024.04.12 |
[백준] 19621 회의실 배정 2 : 자바스크립트(node.js) (0) | 2024.03.26 |