diff --git a/seojimin/week7/11724/Main.java b/seojimin/week7/11724/Main.java new file mode 100644 index 0000000..c6a61b3 --- /dev/null +++ b/seojimin/week7/11724/Main.java @@ -0,0 +1,76 @@ +/** + * 백준 11724번 - 연결 요소의 개수 [BFS 알고리즘] + * + * [문제 요약] + * - 무방향 그래프가 주어진다 + * - 서로 연결된 무리의 개수를 구하라 + * + * [해결 방법] + * - 그래프에 간선에 따른 연결 정보를 담고 + * - 카운트를 올리며 연결 요소들을 방문처리한다 + * + * [시간 복잡도] + * - 최악 전체 노드 순회 -> O(n) + */ + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; + +public class Main { + + static ArrayList[] graph; + static boolean[] visited; + + static int solve(int n, int m, int[][] edges){ + + graph = new ArrayList[n]; + for (int i = 0; i < n; i++) { + graph[i] = new ArrayList<>(); + } + visited = new boolean[n]; + + for (int i = 0; i < m; i++) { + int a = edges[i][0]; + int b = edges[i][1]; + + graph[a-1].add(b-1); + graph[b-1].add(a-1); + } + + int count = 0; + + for (int i = 0; i < n; i++) { + if (!visited[i]){ + count++; + visited[i] = true; + Queue q = new LinkedList<>(); + q.add(i); + + while(!q.isEmpty()){ + int temp = q.poll(); + for (Integer integer : graph[temp]) { + if (!visited[integer]) { + q.add(integer); + visited[integer] = true; + } + } + } + } + } + + return count; + } + + public static void main(String[] args) { + int[][] edges = { + {1,2}, + {2,5}, + {5,1}, + {3,4}, + {4,6} + }; + + System.out.println(solve(6,5,edges)); + } +} \ No newline at end of file diff --git a/seojimin/week7/15591/Main.java b/seojimin/week7/15591/Main.java new file mode 100644 index 0000000..66506ae --- /dev/null +++ b/seojimin/week7/15591/Main.java @@ -0,0 +1,98 @@ +/** + * 백준 15591번 - MooTube (Silver) [BFS 알고리즘] + * + * [문제 요약] + * - 채널마다 서로서로의 유사도가 주어짐 + * - 두 채널이 연결되는 사이 유사도가 적은 채널을 타고 왔으면, 두 채널의 유사도는 최소 유사도에 해당됨 + * - 질의로 오는 출발 채널과 제한 유사도를 토대로, 해당 채널에서 제한 유사도 이상으로 연결된 채널의 개수를 반환 + * + * [해결 방법] + * - 기존 그래프가 배열을 담도록 변경 -> 연결 노드와 함께 유사도를 담음 + * - 각 질의 별로 새롭게 방문 배열을 생성하며, 카운트 역시 새로 생성 + * - 시작 노드에서 부터 bfs를 시작, bfs를 돌면서 다음 노드와의 유사도를 현재까지의 최소 유사도와 비교 + * - 더 작은값을 현재 유사도로 설정한 뒤 k값보다 큰지 체크(작으면 해당 노드를 큐에 담지 않음) + * - 큐에 담으며 카운트++ + * + * [시간 복잡도] + * - 질의 수 q, 모든 노드 수 n -> O(q*n) + */ + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; + +public class Main { + + static ArrayList[] graph; + static boolean[] visited; + + static int solve(int n, int q, int[][] edges, int[][] queries) { + graph = new ArrayList[n + 1]; + for (int i = 1; i <= n; i++) graph[i] = new ArrayList<>(); + + for (int i = 0; i < n - 1; i++) { + int a = edges[i][0]; + int b = edges[i][1]; + int c = edges[i][2]; + + graph[a].add(new int[]{b, c}); + graph[b].add(new int[]{a, c}); + } + + int[] results = new int[q]; + + for (int i = 0; i < q; i++) { + int k = queries[i][0]; + int start = queries[i][1]; + + visited = new boolean[n + 1]; + Queue queue = new LinkedList<>(); + queue.add(new int[]{start, Integer.MAX_VALUE}); + visited[start] = true; + + int count = 0; + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + int now = cur[0]; + int pathMin = cur[1]; + + for (int[] next : graph[now]) { + int nextNode = next[0]; + int usado = next[1]; + if (!visited[nextNode]) { + int newMin = Math.min(pathMin, usado); + if (newMin >= k) { + visited[nextNode] = true; + queue.add(new int[]{nextNode, newMin}); + count++; + } + } + } + } + results[i] = count; + } + + for (int r : results) { + System.out.println(r); + } + + return 0; + } + + public static void main(String[] args) { + int[][] edges = { + {1, 2, 3}, + {2, 3, 2}, + {2, 4, 4} + }; + + int[][] queries = { + {1, 2}, + {4, 1}, + {3, 1} + }; + + solve(4, 3, edges, queries); + } +} \ No newline at end of file diff --git a/seojimin/week7/1743/Main.java b/seojimin/week7/1743/Main.java new file mode 100644 index 0000000..15153d3 --- /dev/null +++ b/seojimin/week7/1743/Main.java @@ -0,0 +1,86 @@ +/** + * 백준 1743번 - 음식물 피하기 [ BFS 알고리즘 ] + * + * [문제 요약] + * - 뭉쳐있는 음식물의 최대 개수 카운ㅌ + * + * [해결 방법] + * - 기존에 하던것처럼 전체 돌면서 음식물 존재 시 bfs 적용 + * - 최댓값 갱신 + * + * [시간 복잡도] + * - N(n*m) + */ + + +import java.util.Queue; +import java.util.LinkedList; + +public class Main { + + static int n,m,k; + static int[][] food; + static boolean[][] visited; + static int[] dx = new int[]{-1, 1, 0, 0}; + static int[] dy = new int[]{0, 0, -1, 1}; + static int max; + + static int solve(int n, int m, int k, int[][] trash){ + food = new int[n][m]; + visited = new boolean[n][m]; + max = 0; + + for (int i = 0; i < k; i++) { + int x = trash[i][0]; + int y = trash[i][1]; + + food[x-1][y-1] = 1; + } + + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (food[i][j] == 1 && !visited[i][j]){ + max = Math.max(max, bfs(i, j)); + } + } + } + + return max; + } + + static int bfs(int a, int b){ + Queue q = new LinkedList<>(); + q.add(new int[]{a,b}); + visited[a][b] = true; + + int count = 1; + + while(!q.isEmpty()){ + int[] pos = q.poll(); + for (int i = 0; i < 4; i++) { + int nx = pos[0] + dx[i]; + int ny = pos[1] + dy[i]; + if (nx >= 0 && nx < n && ny >= 0 && ny < m){ + if (!visited[nx][ny] && food[nx][ny] == 1){ + q.add(new int[]{nx, ny}); + count++; + visited[nx][ny] = true; + } + } + } + } + return count; + } + + public static void main(String[] args) { + int[][] trash = { + {3,2}, + {2,2}, + {3,1}, + {2,3}, + {1,1} + }; + + System.out.println(solve(3,4,5,trash)); + } +} diff --git a/seojimin/week7/18352/Main.java b/seojimin/week7/18352/Main.java new file mode 100644 index 0000000..eb6aba0 --- /dev/null +++ b/seojimin/week7/18352/Main.java @@ -0,0 +1,85 @@ +/** + * 백준 18352번 - 특정 거리의 도시 찾기 [ BFS 알고리즘 ] + * + * [문제 요약] + * - 노드와 단방향 간선이 주어진다 + * - 주어진 노드에서 특정 거리에 있는 노드들을 출력하자 + * + * [해결 방법] + * - 그래프에 노드 및 단방향 간선을 담는다 + * - 출발 노드부터 bfs 시작 + * - 특정 거리에 있는 노드는 리스트에 담고, 정렬 후 출력 + * + * [시간 복잡도] + * - O(n+m) + */ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +public class Main { + + static ArrayList[] graph; + static boolean[] visited; + + static void solve(int n, int m, int k, int x, int[][] edges){ + + graph = new ArrayList[n]; + for (int i = 0; i < n; i++) { + graph[i] = new ArrayList<>(); + } + visited = new boolean[n]; + + for (int i = 0; i < m; i++) { + int a = edges[i][0]; + int b = edges[i][1]; + + graph[a - 1].add(b - 1); + } + + Queue q = new LinkedList<>(); + q.add(new int[]{x-1,0}); + + visited[x-1] = true; + + List result = new ArrayList<>(); + + while(!q.isEmpty()){ + int[] pos = q.poll(); + int now = pos[0]; + int distance = pos[1]; + + for (int i : graph[now]) { + if (!visited[i]) { + q.add(new int[]{i, distance+1}); + visited[i] = true; + if (distance+1 == k) result.add(i); + } + } + } + + if (result.isEmpty()){ + System.out.println(-1); + return; + } + + Collections.sort(result); + for (Integer i : result) { + System.out.println(i+1); + } + } + + public static void main(String[] args) { + int[][] edges = { + {1,2}, + {1,3}, + {2,3}, + {2,4} + }; + + solve(4,4,2,1,edges); + } +} \ No newline at end of file diff --git a/seojimin/week7/2583/Main.java b/seojimin/week7/2583/Main.java new file mode 100644 index 0000000..a04e0a5 --- /dev/null +++ b/seojimin/week7/2583/Main.java @@ -0,0 +1,123 @@ +/** + * 백준 2583번 - 영역 구하기 [BFS 알고리즘] + * + * [문제 요약] + * - 눈금의 간격이 1인 M * N (M, N <= 100) 크기의 모눈종이 + * - 모눈종이 위에 눈금을 맞춰 K개의 직사각형을 그릴 때 + * - K개의 직사각형의 내부를 제외한 나머지 부분이 몇개의 분리된 영역으로 나눠짐 + * - 각 직사각형의 왼쪽 하단 좌표와 우측 상단 좌표가 주어짐 + * - 분리된 영역이 몇개인지 그리고 각 영역별 넓이를 구해 오름차순으로 출력 + * + * [해결 방법] + * - 우선 종이와 직사각형 영역을 다 받고, 직사각형 영역은 별도의 표시 + * - 종이 전체를 순환하며, 방문하지 않고 직사각형 영역 아닌 경우 bfs 함수 호출(함수 호출하며 count 추가) + * - bfs 함수 내에서 연결된 영역 전체 탐색 + * - 탐색 후 계산된 넓이 area 배열에 저장 + * + * [시간 복잡도] + * - bfs 및 영역 전체 순회 -> O(n * m) + * - 정렬 -> O(A logA) + * - 전체 시간 복잡도 -> O(n*m) + * + */ +import java.util.LinkedList; +import java.util.Queue; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Main { + + static int n,m,k; + static int[][] paper; + static boolean[][] visited; + static int[] dx = new int[]{-1, 1, 0, 0}; + static int[] dy = new int[]{0, 0, -1, 1}; + + static void solve(String[] input){ + String[] first = input[0].split(" "); + m = Integer.parseInt(first[0]); + n = Integer.parseInt(first[1]); + k = Integer.parseInt(first[2]); + + paper = new int[m][n]; + visited = new boolean[m][n]; + + // 직사각형 색칠 + for (int i = 0; i < k; i++) { + String[] pos = input[i + 1].split(" "); + int x1 = Integer.parseInt(pos[0]); + int y1 = Integer.parseInt(pos[1]); + int x2 = Integer.parseInt(pos[2]); + int y2 = Integer.parseInt(pos[3]); + for (int j = y1; j < y2; j++) { + for (int l = x1; l < x2; l++) { + paper[j][l] = 1; + } + } + } + + List area = new ArrayList<>(); + for (int i = m-1; i >= 0; i--) { + for (int j = 0; j < n; j++) { + if (!visited[i][j] && paper[i][j] != 1){ + int size = bfs(i, j); + area.add(size); + } + } + } + + System.out.println(area.size()); + Collections.sort(area); + for (int i : area) { + System.out.print(i + " "); + } + } + + static int bfs(int a, int b){ + Queue q = new LinkedList<>(); + q.add(new int[]{a,b}); + visited[a][b] = true; + + int extent = 1; + + while(!q.isEmpty()){ + int[] pos = q.poll(); + + for (int i = 0; i < 4; i++) { + int nx = pos[0] + dx[i]; + int ny = pos[1] + dy[i]; + + if (nx >= 0 && nx < m && ny >= 0 && ny < n){ + if (!visited[nx][ny] && paper[nx][ny] != 1){ + q.add(new int[]{nx, ny}); + extent++; + visited[nx][ny] = true; + } + } + } + } + + return extent; + } + + public static void main(String[] args) { + // 테스트 케이스 입력용 예시 + List testCases = new ArrayList<>(); + testCases.add(new String[]{ + "5 7 3", + "0 2 4 4", + "1 1 2 5", + "4 0 6 2" + }); + + testCases.add(new String[]{ + "3 3 1", + "0 0 1 1" + }); + + for (String[] testCase : testCases) { + solve(testCase); + } + } +} \ No newline at end of file