문제
https://www.acmicpc.net/problem/1260
1260번: DFS와 BFS
첫째 줄에 정점의 개수 N(1 ≤ N ≤ 1,000), 간선의 개수 M(1 ≤ M ≤ 10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는 두 정점의 번호가 주어진다. 어떤 두 정점 사
www.acmicpc.net
단순하게 입력받은 그래프를 dfs, bfs로 탐색한 결과를 출력하는 프로그램이다.
풀이
- dfs는 재귀로, bfs는 Queue 인터페이스를 LinkedList로 구현해 사용했다.
- 인접 행렬 : 그래프 각 정점 사이의 간선을 배열로 표현한다.
- 참고) 인접 행렬을 사용하는 경우, 간선 존재 여부를 상수시간 O(1) 안에 확인할 수 있으나, 정점이 많은 경우 메모리가 낭비된다.
*인접 행렬 사용 방법
만약 4개의 정점(1, 2, 3, 4)의 인접 행렬이라면 (1,1) ~ (4,4) 에 간선 정보를 입력해야 하므로
인접 행렬 크기를 edge[5][5]로 생성한다.
입력받은 값 :
1 2
1 3
1 4
2 4
3 4
1, 2가 간선으로 이어져있으므로 edge[1][2] = edge[2][1] = 1
1, 3이 간선으로 이어져있으므로 edge[1][3] = edge[3][1] = 1
...
문제에서 주어진 그래프는 무방향 그래프이므로 간선이 양방향으로 작용하기 때문에 (a,b) (b,a) 모두 간선 표시
0 | 1 | 2 | 3 | 4 | |
0 | |||||
1 | 1 | 1 | 1 | ||
2 | 1 | 1 | |||
3 | 1 | 1 | |||
4 | 1 | 1 | 1 |
코드
import java.util.*;
import java.util.Queue;
import java.io.*;
public class Main {
//DFS - recursion/Stack
//BFS - LinkedList/Queue
//방문 노드 기록할 boolean 배열 'check'
//간선을 표현할 int 배열 'edge'
static StringBuilder sb = new StringBuilder();
static Queue<Integer> q = new LinkedList<>();
static boolean[] check;
static int[][] edge;
static int N, M, V;
static void dfs(int V) { //recursion
//node를 방문
check[V] = true;
sb.append(V+" ");
//V와 인접 && 아직 방문하지 않은 node를 방문
for(int i=1; i<=N; i++) {
if(edge[V][i]==1 && !check[i]) {
dfs(i);
}
}
}
static void bfs(int V) { //Queue Interface
//시작 node 큐에 넣기
q.offer(V);
check[V] = true;
sb.append(V+" ");
//V와 인접 && 아직 방문하지 않은 node를 방문
while(!q.isEmpty()) {
V = q.poll();
for(int i=1; i<=N; i++) {
if(edge[V][i]==1 && !check[i]) {
q.offer(i);
check[i] = true;
sb.append(i+" ");
}
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
V = Integer.parseInt(st.nextToken());
check = new boolean[N+1]; //인덱스가 0부터 시작하므로 +1
edge = new int[N+1][N+1];
for(int i=0; i<M; i++) { //간선 수만큼 반복
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
edge[a][b] = edge[b][a] = 1;
}
dfs(V);
sb.append("\n");
check = new boolean[N+1];
bfs(V);
bw.write(sb + " ");
bw.close();
}
}
Note
- java.util.* 를 임포트했는데도 계속 큐 선언 코드에 에러가 떠서 java.util.Queue를 임포트했다. 큐는 java.util 패키지에 소속되어있는데 왜 에러가 뜬 걸까..
- sb, q, check, edge, N, M, V는 클래스 내의 dfs, bfs, main 함수 모두 써야 하므로 지역 변수가 아닌 클래스 변수로 선언
- 클래스 변수는 클래스가 메모리에 올라갈 때 생성되며, 인스턴스에 static을 붙여줘야 함
- 주의 : dfs, bfs 함수에서 인접한 노드를 찾는 for문의 조건을 i=1; i<=N 으로 설정해야 한다. i가 노드 번호로 쓰이므로 노드 번호 1부터 N까지를 나타내기 때문. i=0; i<N으로 쓰면 마지막 노드는 검사하지 못한다.
'BOJ' 카테고리의 다른 글
[백준 11724번/JAVA] 연결 요소의 개수 (1) | 2024.03.23 |
---|---|
[백준 2178/JAVA] 미로 탐색 (1) | 2024.03.22 |
[백준 1193번/JAVA] 분수찾기 (0) | 2024.03.17 |
[백준 2903/JAVA] 중앙 이동 알고리즘 (0) | 2024.03.17 |
[백준 2720번/JAVA] 세탁소 사장 동혁 (0) | 2024.03.17 |