위상 정렬
위상정렬(topology sort)은 사이클이 없는 방향 그래프에서 노드 순서를 찾는 알고리즘이다.
진입 차수는 자기 자신을 가리키는 에지의 개수입니다.
줄 세우기
Question - 2252
Code
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class N52_P2252_줄_세우기 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int node = sc.nextInt();
int edge = sc.nextInt();
ArrayList<ArrayList<Integer>> a = new ArrayList<>();
for (int i = 0; i <= node; i++) { // 여기 1부터 넣어도 되지 않을까 ? 안된다.
a.add(new ArrayList<>());
}
// 그래프, 진입 차수 동시에 처리
int[] in = new int[node + 1];
for (int i = 0; i < edge; i++) {
int S = sc.nextInt();
int E = sc.nextInt();
a.get(S).add(E);
in[E]++;
}
Queue<Integer> q = new LinkedList<>();
for (int i = 1; i <= node; i++) {
if (in[i] == 0) q.offer(i); // offer ??
}
while (!q.isEmpty()) {
int now = q.poll();
System.out.print(now + " ");
for (int next : a.get(now)) {
in[next]--;
if (in[next] == 0) q.offer(next);
}
}
}
}
Idea
reference
게임 개발하기
Question - 1516
Code
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class N54_P1516_게임_개발하기 {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int buildingNum = Integer.parseInt(br.readLine());
ArrayList<ArrayList<Integer>> a = new ArrayList<>();
for (int i = 0; i <= buildingNum; i++) {
a.add(new ArrayList<>());
}
int[] in = new int[buildingNum + 1];
int[] time = new int[buildingNum + 1];
for (int i = 1; i <= buildingNum; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
time[i] = Integer.parseInt(st.nextToken());
while (true) {
int preTemp = Integer.parseInt(st.nextToken());
if (preTemp == -1)
break;
a.get(preTemp).add(i);
in[i]++;
}
}
// 위상 정렬
Queue<Integer> q = new LinkedList<>();
for (int i = 1; i <= buildingNum; i++) {
if (in[i] == 0) {
q.offer(i);
}
}
int[] result = new int[buildingNum + 1];
while (!q.isEmpty()) {
int now = q.poll();
for (int next : a.get(now)) {
in[next]--;
result[next] = Math.max(result[next], result[now] + time[now]);
if (in[next] == 0){
q.offer(next);
}
}
}
for (int i = 1; i <= buildingNum; i++) {
System.out.println(result[i] + time[i]);
}
}
}
Idea
reference
임계 경로 구하기
Question - 1948
Code
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class N55_P1948_임계_경로_구하기 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int node = Integer.parseInt(br.readLine()); // 도시
int edge = Integer.parseInt(br.readLine()); // 도로
// 출발 도시의 번호
// 도착 도시 번호
// 도로를 지나는 데 걸리는 시간
ArrayList<ArrayList<dNode>> a = new ArrayList<>();
ArrayList<ArrayList<dNode>> reverse = new ArrayList<>();
// 그래프 초기화
for (int i = 0; i <= node; i++) {
a.add(new ArrayList<>());
reverse.add(new ArrayList<>());
}
// 진입 차수 배열 : 자기 자신을 가리키는 에지의 개수
int[] in = new int[node + 1];
for (int i = 0; i < edge; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int start = Integer.parseInt(st.nextToken()); // 원리 좀 이해해
int end = Integer.parseInt(st.nextToken());
int time = Integer.parseInt(st.nextToken());
a.get(start).add(new dNode(end, time));
reverse.get(end).add(new dNode(start, time));
in[end]++;
}
// 지도를 그리는 사람들이 출발하는 출발 도시와 도착 도시
StringTokenizer st = new StringTokenizer(br.readLine());
int startDosi = Integer.parseInt(st.nextToken());
int endDosi = Integer.parseInt(st.nextToken());
// 위상 정혛
Queue<Integer> q = new LinkedList<>();
q.offer(startDosi);
int[] result = new int[node + 1];
while (!q.isEmpty()) {
int now = q.poll();
for (dNode next : a.get(now)) {
in[next.targetNode]--;
result[next.targetNode] =
Math.max(result[next.targetNode],
result[now] + next.value);
if (in[next.targetNode] == 0) {
q.offer(next.targetNode);
}
}
}
// 위상 정렬 reverse
int count = 0;
boolean visited[] = new boolean[node + 1];
q = new LinkedList<>();
q.offer(endDosi);
visited[endDosi] = true;
while (!q.isEmpty()) {
int now = q.poll();
for (dNode next : reverse.get(now)) {
// 1분도 쉬지 않는 도로 체크
if (result[next.targetNode] + next.value == result[now]) {
count++;
if (visited[next.targetNode] == false) {
visited[next.targetNode] = true;
q.offer(next.targetNode);
}
}
}
}
System.out.println(result[endDosi]);
System.out.println(count);
}
}
class dNode {
int targetNode;
int value;
dNode(int targetNode, int value) {
this.targetNode = targetNode;
this.value = value;
}
}
Idea
개어렵 ㅁㅊ
이들이 출발 도시에서 출발한 후 도착 도시에서 만나기까지 걸리는 최소 시간과, 1분도 쉬지 않고 달려야 하는 사람들이 지나는 도로의 수.
reference
Last updated