diff --git a/problems/SWEA/p1227/Solution.java b/problems/SWEA/p1227/Solution.java new file mode 100644 index 0000000..f08d6ce --- /dev/null +++ b/problems/SWEA/p1227/Solution.java @@ -0,0 +1,134 @@ +/* + * (1227) [S/W 문제해결 기본] 7일차 - 미로2 + * https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV14wL9KAGkCFAYD&categoryId=AV14wL9KAGkCFAYD&categoryType=CODE&problemTitle=1227&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1 + */ + +import java.io.*; +import java.util.*; + +/** + * SW Expert Academy - [S/W 문제해결 기본] 7일차 - 미로2 + * @author YeJun, Jung + * + * [분석] + * - 100x100 미로와, 출발지, 도착지가 주어졌을때 탈출가능 여부를 파악해야 한다. + * - 미로에는 벽, 길 두가지가 있으며 길로만 다닐 수 있다. + * + * [전략] + * - 미로의 출발지에서 DFS를 시작한다. + * - 상하좌우로 이동하면서 목적지에 도달하거나, 모든 장소를 방문할때가지 반복한다. + * - 목적지를 찾았다면 '1' 아니면 '0'을 화면에 출력한다. + */ +public class Solution { + static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out)); + + // ---------------------------------------------------------- + + public static void main(String[] args) throws IOException { + final int testCount = 10; + + for (int testCase = 1; testCase <= testCount; testCase++) { + reader.readLine(); // 테스트케이스 입력 + + new Solution(testCase).run(); + } + } + + // ---------------------------------------------------------- + + static final int BOARD_SIZE = 100; + static final char ROAD = '0'; + static final char WALL = '1'; + static final char START = '2'; + static final char GOAL = '3'; + + static final int DIR_LEN = 4; + static final int[] DIR_X = { 0, 0, -1, 1 }; + static final int[] DIR_Y = { -1, 1, 0, 0 }; + + static char[][] board = new char[BOARD_SIZE][BOARD_SIZE]; + + int testCase; + int answer; + Pos start; + boolean[][] visited; + + public Solution(int testCase) { + this.testCase = testCase; + } + + public void run() throws IOException { + input(); + solve(); + print(); + } + + private void input() throws IOException { + char[] input; + for (int y = 0; y < BOARD_SIZE; y++) { + input = reader.readLine().trim().toCharArray(); + + for (int x = 0; x < BOARD_SIZE; x++) { + board[y][x] = input[x]; + + if (board[y][x] == START) { + start = new Pos(x, y); + } + } + } + } + + private void solve() { + visited = new boolean[BOARD_SIZE][BOARD_SIZE]; + visited[start.y][start.x] = true; + + answer = dfs(start.x, start.y) ? 1 : 0; + } + + private boolean dfs(int x, int y) { + if (board[y][x] == GOAL) return true; + + for (int dir = 0; dir < DIR_LEN; dir++) { + int nx = x + DIR_X[dir]; + int ny = y + DIR_Y[dir]; + + if (!isInsideBoard(nx, ny) || + board[ny][nx] == WALL || + visited[ny][nx] + ) { + continue; + } + + visited[ny][nx] = true; + if (dfs(nx, ny)) return true; + } + + return false; + } + + private boolean isInsideBoard(int x, int y) { + return x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE; + } + + private void print() throws IOException { + writer.write("#" + testCase); + writer.write(" " + answer); + writer.write("\n"); + writer.flush(); + } + + // ---------------------------------------------------------- + + private static class Pos { + int x; + int y; + + public Pos(int x, int y) { + this.x = x; + this.y = y; + } + } + + // ---------------------------------------------------------- +} diff --git a/problems/SWEA/p1267/Solution.java b/problems/SWEA/p1267/Solution.java new file mode 100644 index 0000000..c47b6d5 --- /dev/null +++ b/problems/SWEA/p1267/Solution.java @@ -0,0 +1,118 @@ +/* + * (1267) [S/W 문제해결 응용] 10일차 - 작업순서 + * https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV18TrIqIwUCFAZN&categoryId=AV18TrIqIwUCFAZN&categoryType=CODE&problemTitle=1267&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1 + */ + +import java.io.*; +import java.util.*; + +/** + * SW Expert Academy - 1267. [S/W 문제해결 응용] 10일차 - 작업순서 + * @author YeJun, Jung + * + * [분석] + * - 각 작업에는 선행작업이 있을 수 있다. + * - 간선이 없는 노드가 있을 수 있다.(즉 선행작업이 없는 노드가 존재할 수 있음) + * + * [전략] + * - 위상정렬을 사용해서 선행작업이 먼저 수행되도록 순서를 만든다. + * - 선행작업이 없는 노드의 작업 순서는 중요하지 않다. + */ +public class Solution { + static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer input; + + // ---------------------------------------------------------- + + public static void main(String[] args) throws IOException { + final int testCount = 10; + + for (int testCase = 1; testCase <= testCount; testCase++) { + new Solution(testCase).run(); + } + } + + // ---------------------------------------------------------- + + int testCase; + int[] workOrder; + + int nodeLen; + int edgeLen; + List> graph; + int[] inorder; + + public Solution(int testCase) { + this.testCase = testCase; + } + + public void run() throws IOException { + input(); + solve(); + print(); + } + + private void input() throws IOException { + getLine(); + nodeLen = Integer.parseInt(input.nextToken()); + edgeLen = Integer.parseInt(input.nextToken()); + + graph = new ArrayList<>(nodeLen + 1); + for (int node = 0; node <= nodeLen; node++) { + graph.add(new ArrayList<>()); + } + + int nodeA, nodeB; + inorder = new int[nodeLen + 1]; + getLine(); + while (input.hasMoreTokens()) { + nodeA = Integer.parseInt(input.nextToken()); + nodeB = Integer.parseInt(input.nextToken()); + + graph.get(nodeA).add(nodeB); + inorder[nodeB]++; + } + } + + private void solve() { + workOrder = new int[nodeLen]; + + topologicalSort(); + } + + private void topologicalSort() { + int size = 0; + Queue q = new ArrayDeque<>(); + + for (int node = 1; node <= nodeLen; node++) { + if (inorder[node] == 0) q.offer(node); + } + + while (!q.isEmpty()) { + int peek = q.poll(); + workOrder[size++] = peek; + + for (int child : graph.get(peek)) { + if (--inorder[child] == 0) q.offer(child); + } + } + } + + private void print() throws IOException { + writer.write("#" + testCase + " "); + + for (int node : workOrder) { + writer.write(node + " "); + } + + writer.write("\n"); + writer.flush(); + } + + // ---------------------------------------------------------- + + private static void getLine() throws IOException { + input = new StringTokenizer(reader.readLine().trim()); + } +} diff --git a/problems/SWEA/p2105/Solution.java b/problems/SWEA/p2105/Solution.java new file mode 100644 index 0000000..e8c04de --- /dev/null +++ b/problems/SWEA/p2105/Solution.java @@ -0,0 +1,187 @@ +/* + * (2105) [모의 SW 역량테스트] 디저트 카페 + * https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5VwAr6APYDFAWu&categoryId=AV5VwAr6APYDFAWu&categoryType=CODE&problemTitle=2105&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1 + */ + +import java.io.*; +import java.util.*; + +/** + * SW Expert Academy - 2105. [모의 SW 역량테스트] 디저트 카페 + * @author YeJun, Jung + * + * [분석] + * - 보드의 각 요소에서 출발해서 대각선 방향으로 이동한다. + * - 카페 투어중에 같은 숫자를 만나선 안된다. + * - 특정 위치에서 우상향으로 width만큼, 우하향으로 height만큼 움직이면 + * 사각형 path가 만들어진다. + * + * [전략] + * * search(): 보드의 각 요소를 방문하면서... + * - 일단 우상향 방향으로 간다. + * * pathUp(): 그 다음 부터 DFS 하면서 가능한 width를 만들어본다... + * (1-1) 계속 우상향으로 이동하거나(재귀 호출) + * (1-2) 꺽어서 우하양으로 전환하거나 + * * pathDown(): 그 다음 부터 DFS 하면서 가능한 height를 만들어본다... + * (2-1) 계속 우하양으로 이동하거나(재귀호출) + * (2-2) 그만 진행하고 만들어진 path 값을 계산해보거나 + * * countDesert(): 조합된 startX, startY, width, height를 바탕으로 + * path를 만들고 몇 개의 디저트를 먹을 수 있는지 카운트 한다. + * - 보드 밖으로 나가거나 디저트가 중복되면 (-1)을 반환한다. + */ +public class Solution { + static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer input; + + // ---------------------------------------------------------- + + public static void main(String[] args) throws IOException { + final int testCount = Integer.parseInt(reader.readLine().trim()); + + for (int testCase = 1; testCase <= testCount; testCase++) { + new Solution(testCase).run(); + } + } + + // ---------------------------------------------------------- + + static final int MAX_DESSERT = 100; // 디저트 종류 + + static final int RIGHT_UP = 0; + static final int RIGHT_DOWN = 1; + static final int LEFT_DOWN = 2; + static final int LEFT_UP = 3; + + static final int[] DIR_X = { 1, 1, -1, -1 }; // RIGHT-UP, RIGHT-DOWN, LEFT-DOWN, LEFT-UP + static final int[] DIR_Y = { -1, 1, 1, -1 }; // RIGHT-UP, RIGHT-DOWN, LEFT-DOWN, LEFT-UP + + int testCase; + int answer; + int boardSize; + int[][] board; + int startX; // 지금 탐색중인 path의 시작점 X + int startY; // 지금 탐색중인 path의 시작점 Y + + public Solution(int testCase) { + this.testCase = testCase; + } + + public void run() throws IOException { + input(); + solve(); + print(); + } + + private void input() throws IOException { + boardSize = Integer.parseInt(reader.readLine().trim()); + board = new int[boardSize][boardSize]; + + for (int y = 0; y < boardSize; y++) { + getLine(); + + for (int x = 0; x < boardSize; x++) { + board[y][x] = Integer.parseInt(input.nextToken()); + } + } + } + + private void solve() { + answer = -1; + + search(); + } + + private void search() { + for (int y = 1; y < boardSize; y++) { + for (int x = 0; x < boardSize - 1; x++) { + startX = x; + startY = y; + + answer = Math.max(answer, makePath(x, y)); + } + } + } + + private int makePath(int x, int y) { + int nx = x + DIR_X[RIGHT_UP]; + int ny = y + DIR_Y[RIGHT_UP]; + + if (!isInsideBoard(nx, ny)) return -1; + + return pathUp(nx, ny, 1); + } + + private int pathUp(int x, int y, int width) { + int r1 = -1, r2 = -1; + int nx = x + DIR_X[RIGHT_UP]; + int ny = y + DIR_Y[RIGHT_UP]; + + if (isInsideBoard(nx, ny)) { + r1 = pathUp(nx, ny, width + 1); + } + + r2 = pathDown(x, y, width, 0); + + return Math.max(r1, r2); + } + + private int pathDown(int x, int y, int width, int height) { + int r1 = -1, r2 = -1; + int nx = x + DIR_X[RIGHT_DOWN]; + int ny = y + DIR_Y[RIGHT_DOWN]; + + if (isInsideBoard(nx, ny)) { + r1 = pathDown(nx, ny, width, height + 1); + } + + r2 = height > 0 ? countDessert(width, height) : -1; + + return Math.max(r1, r2); + } + + private int countDessert(int width, int height) { + int result = 0; + int cx = startX, cy = startY; + int dir = 0; + boolean[] visited = new boolean[MAX_DESSERT + 1]; + + for (int c0 = 0; c0 < 2; c0++) { + for (int c1 = 0; c1 < width + height; c1++) { + if (!isInsideBoard(cx, cy)) return -1; + + int dessert = board[cy][cx]; + + if (visited[dessert]) return -1; // 만약 가계 중복되면 -1 반환 + + visited[dessert] = true; + result++; + + if (c1 == width) dir++; + cx += DIR_X[dir]; + cy += DIR_Y[dir]; + } + + dir++; + } + + return result; + } + + private boolean isInsideBoard(int x, int y) { + return x >= 0 && x < boardSize && y >= 0 && y < boardSize; + } + + private void print() throws IOException { + writer.write("#" + testCase); + writer.write(" " + answer); + writer.write("\n"); + writer.flush(); + } + + // ---------------------------------------------------------- + + private static void getLine() throws IOException { + input = new StringTokenizer(reader.readLine().trim()); + } +} diff --git a/problems/baekjoon/p17135/Main.java b/problems/baekjoon/p17135/Main.java new file mode 100644 index 0000000..196ebd2 --- /dev/null +++ b/problems/baekjoon/p17135/Main.java @@ -0,0 +1,189 @@ +/* + * (17135) 캐슬 디펜스 + * https://www.acmicpc.net/problem/17135 + */ + +import java.io.*; +import java.util.*; + +/** + * Baekjoon - 캐슬 디펜스 + * @author YeJun, Jung + * + * [분석] + * - 궁수 3명의 x위치는 주어지지 않는다. (직접 적절히 배치해야 한다) + * - 궁수는 같은 거리의 적들이 있다면 제일 왼쪽에 있는 적을 노린다. + * - 적들은 매일 +1만큼 y좌표를 이동한다. + * + * [전략] + * - 궁수 3명의 위치는 가능한 조합들을 모두 시도해 본다. + * - boardWidth 만큼의 칸에서 3개를 선택하는 것 + * - prevPermutation과 mask 배열을 사용해서 구현한다. + * - 궁수들의 위치 조합들에 대해서 시뮬레이션을 통해 죽인 적의 개수를 센다. + * - 적들의 위치를 모두 Queue에 삽입하고 시뮬레이션을 시작한다. + * - boardHeight 만큼의 일수 혹은 모든 적들의 삭제 전까지 반복한면서... + * - 각 헌터의 위치별 최소 거리의 적을 식별한다. + * - 이때 거리제한으로 인해 맞출수 있는 적이 하나도 없을 수 도 있다. + * - 각 헌터가 맞춘 적은 HashSet에 보관해둔다. + * - 헌터가 맞춘 적과 이미 성까지 도달한 적을 제외한 모든 적을 y좌표 +1하고 Queue에 삽입한다. + * - 헌터가 맞춘 적들의 수를 합하여 최대값이 되는 조합을 찾는다. + */ +public class Main { + static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer input; + + // ---------------------------------------------------------- + + public static void main(String[] args) throws IOException { + new Main().run(); + } + + // ---------------------------------------------------------- + + int answer; + int boardHeight; + int boardWidth; + int attackDistance; + char[][] board; + int[] select; + List enemyList; + Set enemyKill; + Queue enemyQ; + + public void run() throws IOException { + input(); + solve(); + print(); + } + + private void input() throws IOException { + getLine(); + boardHeight = Integer.parseInt(input.nextToken()); + boardWidth = Integer.parseInt(input.nextToken()); + attackDistance = Integer.parseInt(input.nextToken()); + + board = new char[boardHeight][boardWidth]; + enemyList = new ArrayList<>(boardHeight * boardWidth); // Capacity Reservation + + for (int y = 0; y < boardHeight; y++) { + getLine(); + + for (int x = 0; x < boardWidth; x++) { + board[y][x] = input.nextToken().charAt(0); + if (board[y][x] == '1') enemyList.add(new Pos(x, y)); + } + } + } + + private void solve() { + answer = 0; + + select = new int[boardWidth]; + Arrays.fill(select, 0, 3, 1); + + do { + answer = Math.max(answer, runSimulation()); + } while (prevPermutation(select)); + } + + private int runSimulation() { + int result = 0; + enemyKill = new HashSet<>(); + enemyQ = new ArrayDeque<>(enemyList); + + for (int day = 0; day < boardHeight && !enemyQ.isEmpty(); day++) { + for (int hunterX = 0; hunterX < boardWidth; hunterX++) { + if (select[hunterX] == 0) continue; + + Pos pos = shootFrom(hunterX); + if (pos != null) enemyKill.add(pos); + } + + result += enemyKill.size(); + + int qSize = enemyQ.size(); + for (int cnt = 0; cnt < qSize; cnt++) { + Pos peek = enemyQ.poll(); + if (enemyKill.contains(peek) || peek.y + 1 >= boardHeight) continue; + + enemyQ.offer(new Pos(peek.x, peek.y + 1)); + } + enemyKill.clear(); + } + + return result; + } + + private Pos shootFrom(int hunterX) { + Pos pos = null; + int distance = Integer.MAX_VALUE; + int current; + + for (Pos enemy : enemyQ) { + current = distanceCalc(hunterX, boardHeight, enemy.x, enemy.y); + + if (current > attackDistance) continue; + + if ((current < distance) || + (current == distance && enemy.x < pos.x) + ) { + distance = current; + pos = enemy; + } + } + + return pos; + } + + private int distanceCalc(int x0, int y0, int x1, int y1) { + return Math.abs(x0 - x1) + Math.abs(y0 - y1); + } + + private void print() throws IOException { + writer.write(answer + "\n"); + writer.flush(); + } + + // ---------------------------------------------------------- + + private static class Pos { + int x; + int y; + + public Pos(int x, int y) { + this.x = x; + this.y = y; + } + + @Override public String toString() { return String.format("[%d, %d]", x, y); } + @Override public int hashCode() { return Objects.hash(x, y); } + @Override public boolean equals(Object obj) { + Pos another = (Pos)obj; + return this.x == another.x && this.y == another.y; + } + } + + // ---------------------------------------------------------- + + private static void getLine() throws IOException { + input = new StringTokenizer(reader.readLine().trim()); + } + + private static boolean prevPermutation(int[] x) { + int n = x.length - 1, a = n, b = n; + while (a > 0 && x[a - 1] <= x[a]) a--; + if (a == 0) return false; + while (x[a - 1] <= x[b]) b--; + swap(x, a - 1, b); reverse(x, a, n); + return true; + } + + private static void swap(int[] x, int a, int b) { + int t = x[a]; x[a] = x[b]; x[b] = t; + } + + private static void reverse(int[] x, int a, int b) { + while (a < b) swap(x, a++, b--); + } +} diff --git a/problems/baekjoon/p1759/Main.java b/problems/baekjoon/p1759/Main.java new file mode 100644 index 0000000..331e8f0 --- /dev/null +++ b/problems/baekjoon/p1759/Main.java @@ -0,0 +1,134 @@ +/* + * (1759) 암호 만들기 + * https://www.acmicpc.net/problem/1759 + */ + +import java.io.*; +import java.util.*; + +/** + * Baekjoon - 암호 만들기 + * @author YeJun, Jung + * + * [분석] + * - 주어진 알파벳으로 조건을 만족하는 모든 조합을 만들어야 한다. + * - 정답을 출력할때는 사전순으로 정렬되어야 한다. + * + * [전략] + * - 입력된 알파벳 배열을 사전순으로 정렬하여, 조합 과정에서 사전순으로 암호문이 생성되도록 한다. + * - prevPermutation을 응용하여 조합을 생성한다. + * - switch ~ case 구문으로 모음 개수와 자음 개수를 카운트 하여 암호문 조건을 확인한다. + */ +public class Main { + static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer input; + + // ---------------------------------------------------------- + + public static void main(String[] args) throws IOException { + new Main().run(); + } + + // ---------------------------------------------------------- + + int strLen; + int charLen; + String[] charArr; + int[] select; + + public void run() throws IOException { + input(); + solve(); + + writer.flush(); + } + + private void input() throws IOException { + getLine(); + strLen = Integer.parseInt(input.nextToken()); + charLen = Integer.parseInt(input.nextToken()); + + getLine(); + charArr = new String[charLen]; + for (int index = 0; index < charLen; index++) { + charArr[index] = String.valueOf(input.nextToken().charAt(0)); + } + } + + private void solve() throws IOException { + select = new int[charLen]; + Arrays.fill(select, 0, strLen, 1); + + Arrays.sort(charArr); + + makeCombination(); + } + + private void makeCombination() throws IOException { + StringBuilder str; + + do { + str = new StringBuilder(); + + for (int index = 0; index < charLen; index++) { + if (select[index] == 0) continue; + str.append(charArr[index]); + } + + if (isCorrect(str)) { + print(str); + } + } while (prevPermutation(select)); + } + + private boolean isCorrect(StringBuilder str) { + int c0 = 0; // 모음(a, i, u, e, o) + int c1 = 0; // 자음 + int length = str.length(); + + for (int index = 0; index < length; index++) { + switch (str.charAt(index)) { + case 'a': + case 'i': + case 'u': + case 'e': + case 'o': + c0++; + break; + default: + c1++; + } + } + + return c0 >= 1 && c1 >= 2; + } + + private void print(StringBuilder str) throws IOException { + str.append("\n"); + writer.write(str.toString()); + } + + // ---------------------------------------------------------- + + private static void getLine() throws IOException { + input = new StringTokenizer(reader.readLine().trim()); + } + + private static boolean prevPermutation(int[] x) { + int n = x.length - 1, a = n, b = n; + while (a > 0 && x[a - 1] <= x[a]) a--; + if (a == 0) return false; + while (x[a - 1] <= x[b]) b--; + swap(x, a - 1, b); reverse(x, a, n); + return true; + } + + private static void swap(int[] x, int a, int b) { + int t = x[a]; x[a] = x[b]; x[b] = t; + } + + private static void reverse(int[] x, int a, int b) { + while (a < b) swap(x, a++, b--); + } +} diff --git a/problems/baekjoon/p2252/Main.java b/problems/baekjoon/p2252/Main.java new file mode 100644 index 0000000..018d2d0 --- /dev/null +++ b/problems/baekjoon/p2252/Main.java @@ -0,0 +1,111 @@ +/* + * (2252) 줄 세우기 + * https://www.acmicpc.net/problem/2252 + */ + +import java.io.*; +import java.util.*; + +/** + * Baekjoon - 줄 세우기 + * @author YeJun, Jung + * + * [분석] + * - 전체 학생이 아닌 일부 학생들만 비교를 하고 있다. + * - 정답이 여러개 존재할 수 있다. + * + * [전략] + * - 학생들의 키에 대한 관계를 그래프로 나타낸다. + * - 위상정렬을 사용해서 각 학생 노드의 방문 순서가 키를 기준으로 오름차순되도록 한다. + * - 정렬된 노드의 방문 순서를 화면에 표시한다. + */ +public class Main { + static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer input; + + // ---------------------------------------------------------- + + public static void main(String[] args) throws IOException { + new Main().run(); + } + + // ---------------------------------------------------------- + + int[] answer; + int size; + + int nodeLen; + int edgeLen; + List> graph; + int[] inorder; + + public void run() throws IOException { + input(); + solve(); + print(); + } + + private void input() throws IOException { + getLine(); + nodeLen = Integer.parseInt(input.nextToken()); + edgeLen = Integer.parseInt(input.nextToken()); + + int nodeA, nodeB; + inorder = new int[nodeLen + 1]; + graph = new ArrayList<>(nodeLen + 1); + + for (int index = 0; index <= nodeLen; index++) { + graph.add(new ArrayList<>()); + } + + for (int cnt = 0; cnt < edgeLen; cnt++) { + getLine(); + nodeA = Integer.parseInt(input.nextToken()); + nodeB = Integer.parseInt(input.nextToken()); + + graph.get(nodeA).add(nodeB); + inorder[nodeB]++; + } + } + + private void solve() { + answer = new int[nodeLen]; + + topologicalSort(); + } + + private void topologicalSort() { + size = 0; + Queue q = new ArrayDeque<>(); + + for (int node = 1; node <= nodeLen; node++) { + if (inorder[node] != 0) continue; + q.offer(node); + } + + while (!q.isEmpty()) { + int peek = q.poll(); + + answer[size++] = peek; + + for (int child : graph.get(peek)) { + if (--inorder[child] == 0) q.offer(child); + } + } + } + + private void print() throws IOException { + for (int index = 0; index < nodeLen; index++) { + writer.write(answer[index] + " "); + } + writer.write("\n"); + writer.flush(); + } + + // ---------------------------------------------------------- + + private static void getLine() throws IOException { + input = new StringTokenizer(reader.readLine().trim()); + } +}