티어 : Sliver 2
정답여부 : 정답
알고리즘 유형 : 그래프 이론, 그래프 탐색, 너비 우선 탐색, 깊이 우선 탐색
시간 제한 : 3초
💡문제
방향 없는 그래프가 주어졌을 때, 연결 요소 (Connected Component)의 개수를 구하는 프로그램을 작성하시오.
💡입력
첫째 줄에 정점의 개수 N과 간선의 개수 M이 주어진다. (1 ≤ N ≤ 1,000, 0 ≤ M ≤ N×(N-1)/2) 둘째 줄부터 M개의 줄에 간선의 양 끝점 u와 v가 주어진다. (1 ≤ u, v ≤ N, u ≠ v) 같은 간선은 한 번만 주어진다.
💡출력
첫째 줄에 연결 요소의 개수를 출력한다 .
💡예제 입력1
6 5
1 2
2 5
5 1
3 4
4 6
💡예제 출력1
2
💡예제 입력2
6 8
1 2
2 5
5 1
3 4
4 6
5 4
2 4
2 3
💡예제 출력2
1
💡문제 분석 요약
- 연결된 노드의 개수를 구하면 되는 문제
💡알고리즘 설계
- N : 정점의 개수
- M : 간선의 개수
- u, v: 간선으로 이루어진 정점들
- arr : 그래프
- visit: 노드를 방문확인용
- N과 M을 입력받음
- 각 연결되는 노드 u, v를 입력받음
- 각 입력받은 노드는 연결되어 있다는 1로 표시
- 각 노드끼리 연결되어 있는 팀을 찾기 위해 DFS , BFS 실행
- DFS
- 시작점을 받아오고 방문했던 노드로 표시
- 인접한 노드를 찾도록 재귀함수 실행
- BFS
- 시작점 노드를 받아 que에 추가하여 방문했던 노시 표시
- temp에 시작점 노드를 꺼내주고 인접한 노드를 찾아줌 찾게 된다면 큐에 추가 해주고 방문했던 노드로 표시
- 큐가 비어있다면 노드는 없는것으로 반복문 종료
💡시간복잡도
- O(M + N^2)
💡코드
import java.util.*;
import java.io.*;
public class Main {
static int N , M;
static int u , v;
static int[][] arr;
static boolean []visit;
static int cnt;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
arr = new int[N+1][N+1];
visit = new boolean[N+1];
for(int i = 0; i < M; i++) {
StringTokenizer sts = new StringTokenizer(br.readLine());
u = Integer.parseInt(sts.nextToken());
v = Integer.parseInt(sts.nextToken());
arr[u][v] = arr[v][u] = 1;
}
for(int i = 1; i <= N; i++) {
if(!visit[i]) {
dfs(i);
cnt++;
}
}
System.out.println(cnt);
}
public static void dfs(int start) {
visit[start] = true;
for(int i = 1; i <= N; i++) {
if(arr[start][i] == 1 && !visit[i]) {
dfs(i);
}
}
}
}
💡 틀린 이유
저번 DFS , BFS 구현 문제와 같아서 BFS로도 풀어봤다. 어려운건 없었다.
💡 틀린 부분 수정 or 다른 풀이
import java.io.*;
import java.util.*;
public class Main {
static int N , M;
static int u , v;
static int[][] arr;
static boolean []visit;
static int cnt;
static Queue<Integer>que = new LinkedList<>();
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
arr = new int[N+1][N+1];
visit = new boolean[N+1];
for(int i = 0; i < M; i++) {
StringTokenizer sts = new StringTokenizer(br.readLine());
u = Integer.parseInt(sts.nextToken());
v = Integer.parseInt(sts.nextToken());
arr[u][v] = arr[v][u] = 1;
}
for(int i =1; i <= N; i++) {
if(!visit[i]) {
bfs(i);
cnt++;
}
}
System.out.println(cnt);
}
public static void bfs(int start) {
que.offer(start);
visit[start] = true;
while(!que.isEmpty()) {
int temp = que.poll();
for(int i = 1; i <=N; i++) {
if(arr[temp][i] == 1 && !visit[i]) {
que.offer(i);
visit[i] = true;
}
}
}
}
}
💡 느낀점 or 기억할정보
이제까지는 입력받은 수가 x, y 위치라 위치를 찾는 구조라서 이해하기 쉬웠는데 노드를 무방향 그래프로 생각을 하면 이해하기가 생각보다 힘들다. 그리고 내가 DFS, BFS 코드를 이해보다는 외운감이 있는거 같다. 그래서 그림을 그리면서 하나하나 조건을 따지며 재귀함수 , 큐를 직접 구현해보면서 로그를 찍어보니 코드가 어떻게 동작하는지 조금 더 이해하기 수월해진거 같다.
'CodingTest > Baekjoon' 카테고리의 다른 글
[B0J]미로탐색(2178번) (0) | 2024.06.19 |
---|---|
[B0J]숨바꼭질(1697번) (0) | 2024.06.19 |
[B0J]유기농 배추(1012번) (0) | 2024.06.19 |
[B0J]단지번호붙이기(2667번) (0) | 2024.06.19 |
[B0J]DFS와 BFS(1260번) (0) | 2024.06.19 |