코딩테스트/알고리즘
그래프 탐색 유형 오답노트
초코chip
2024. 8. 21. 15:35
정리

그래프 탐색
바이러스 - 실버3
https://www.acmicpc.net/problem/2606

문제 유형:
- 노드 형태의 그래프 형태
- 시작점에 연결된 노드의 개수를 세는 문제
- 노드 관점의 그래프 자료구조를 사용했을떄 dfs/bfs 아무거나 상관x
- 그냥 연결된 모든 노드를 탐방을 하고 연결된 노드 개수를 세는 문제 -> 스택 or 큐에 넣을때마다 count 증가
단지번호붙이기 - 실버1
https://www.acmicpc.net/problem/2667

문제 유형:
- 2차원 배열 형태의 그래프 형태
- 연결된 모든 노드의 개수를 세는 문제
- 즉, 모든 노드를 시작점으로 다 탐색을 해야함
해결책:
- graph[1][1] ~ graph[n][n]까지 모든 노드를 시작 지점으로 하고 탐색을 진행
- 단, 이미 방문한 노드이거나 탐색 불가 지역(예: 벽)이면 탐색x

- 노드 관점에서는 이웃 노드를 간선 정보를 확인해야 했지만, 2차원 배열 형태는 상하좌우가 기본적으로 연결이 되어있는 형태
- 따라서, 방향 벡터로 이웃된 4개의 노드를 다음 탐색에 넣을지 말지 판단하면 되는 것
2차원 배열 형태 그래프 탐색에서 필요한 것
2차원 배열 형태의 그래프와 방문 확인 배열 | bfs | 2차원 배열 위치 |
![]() |
![]() |
![]() |
핵심은 2차원 배열 형태는 어차피 상하좌우가 다 연결이 되어있기에 노드의 값(2차원 배열 값)만 입력받아 방향 벡터로 처리하는 방향으로 가자
더보기
package org.woojin.graphSearch;
import java.io.*;
import java.util.*;
public class 단지번호붙이기 {
static int n;
static int[][] graph;
static boolean[][] visited;
static int[] dx = {-1, 1, 0, 0};
static int[] dy = {0, 0, -1, 1};
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.valueOf(br.readLine());
graph = new int[n+1][n+1];
visited = new boolean[n+1][n+1];
//입력
for (int i = 0; i < n; i++) {
String line = br.readLine();
for (int j = 0; j < n; j++) {
graph[i+1][j+1] = line.charAt(j) - '0';
}
}
//입력
ArrayList<Integer> result = new ArrayList<>();
for(int i=1; i<=n; i++){
for (int j=1; j<=n; j++){
if(graph[i][j]== 0 || visited[i][j]){
continue;
}
result.add(bfs(i,j));
}
}
Collections.sort(result);
StringBuilder sb = new StringBuilder();
sb.append(result.size()).append("\n");
for(int r : result){
sb.append(r).append("\n");
}
System.out.println(sb);
}
public static int bfs(int x, int y) {
Stack<Node> s = new Stack<>();
s.push(new Node(x,y));
visited[x][y] = true;
int count = 1;
while(!s.isEmpty()){
Node now = s.pop();
//방향 벡터 버전
for(int i=0; i<4; i++){
int nx = now.x + dx[i];
int ny = now.y + dy[i];
if(nx >= 1 && nx <= n && ny >= 1 && ny <= n){
if(graph[nx][ny] != 0 && !(visited[nx][ny])){
s.push(new Node(nx, ny));
visited[nx][ny] = true;
count++;
}
}
}
}
return count;
}
static class Node{
int x;
int y;
public Node(int x, int y){
this.x = x;
this.y = y;
}
}
}
봄버맨 - 실버1

문제 유형
- 2차원 배열 형태의 그래프 형태
- 연결된 노드에 작업을 하는 문제 ( 폭탄 폭발 처리 )
해결 방법
- 매초마다 폭탄이 폭발 처리만 bfs/dfs를 사용해서 하는 문제
- 매초마다 폭탄 심고, 폭탄 카운트 다운 하는건 따로 구현해야하는 문제였음 ( 코드가 덕분에 길어짐 )
더보기
package org.woojin.graphSearch;
import java.io.*;
import java.util.*;
public class 붐버맨 {
static int r;
static int c;
static int n;
static int[][] graph;
static boolean[][] visited;
static int[] dx = {-1, 1, 0, 0};
static int[] dy = {0, 0, -1, 1};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
r = Integer.valueOf(st.nextToken());
c = Integer.valueOf(st.nextToken());
n = Integer.valueOf(st.nextToken());
graph = new int[r+1][c+1];
visited = new boolean[r+1][c+1];
String str;
for(int i=1; i<=r; i++){
str = br.readLine();
for(int j=0; j<c; j++){
if(str.charAt(j) == 'O'){
graph[i][j+1] = 3;
}
}
}
if(n<=1){
printGraph();
return;
}
for(int i=2; i<=n; i++){
countBom();
if(i % 2 == 0){
makeBom();
}
resetVisited();
checkBfs();
}
printGraph();
}
// 한번의 bfs를 수행 후 방문 배열 초기화
public static void resetVisited(){
for(int i=1; i<=r; i++){
Arrays.fill(visited[i], false);
}
}
// 폭탄 설치 함수
public static void makeBom(){
for(int i=1; i<=r; i++) {
for (int j = 1; j <= c; j++) {
if(graph[i][j] == 0){
graph[i][j] = 4;
}
}
}
}
// 폭탄 시간 감소 ( 1이 되면 터짐 )
public static void countBom(){
for(int i=1; i<=r; i++) {
for (int j = 1; j <= c; j++) {
if(graph[i][j] > 1){
graph[i][j] -= 1;
}
}
}
}
// 2차원 배열 그래프 각 지점마다다 bfs 시작
public static void checkBfs(){
for(int i=1; i<=r; i++) {
for (int j = 1; j <= c; j++) {
//단, 방문x + 폭탄 시간이 1 남은 것만 bfs시작
if((!visited[i][j]) && graph[i][j] == 1 ){
bfs(i,j);
}
}
}
}
public static void bfs(int x, int y){
Stack<Node> s = new Stack<>();
s.push(new Node(x,y));
visited[x][y] = true;
while(!s.isEmpty()){
Node now = s.pop();
graph[x][y] = 0;
for(int i=0; i<4; i++){
int nx = now.x + dx[i];
int ny = now.y + dy[i];
if(nx >= 1 && nx <= r && ny >=1 && ny <= c){
//이웃노드 폭탄 처리 하는데
if(!visited[nx][ny]){
//이웃 노드도 폭탄 시간이 1 남았으면 동시 폭발을 위해 추가 탐색
if(graph[nx][ny] == 1){
s.push(new Node(nx, ny));
}
graph[nx][ny] = 0;
visited[nx][ny] = true;
}
}
}
}
}
public static void printGraph(){
StringBuilder sb = new StringBuilder();
for(int i=1; i<=r; i++){
for(int j=1; j<=c; j++){
if(graph[i][j] != 0){
sb.append('O');
} else {
sb.append('.');
}
}
sb.append("\n");
}
System.out.print(sb);
}
static class Node{
int x;
int y;
public Node(int x, int y){
this.x = x;
this.y = y;
}
}
}