반응형
1) 문제
https://www.acmicpc.net/problem/1707
문제
그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있을 때, 그러한 그래프를 특별히 이분 그래프 (Bipartite Graph) 라 부른다.
그래프가 입력으로 주어졌을 때, 이 그래프가 이분 그래프인지 아닌지 판별하는 프로그램을 작성하시오.
입력
입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V와 간선의 개수 E가 빈 칸을 사이에 두고 순서대로 주어진다. 각 정점에는 1부터 V까지 차례로 번호가 붙어 있다. 이어서 둘째 줄부터 E개의 줄에 걸쳐 간선에 대한 정보가 주어지는데, 각 줄에 인접한 두 정점의 번호 u, v (u ≠ v)가 빈 칸을 사이에 두고 주어진다.
출력
K개의 줄에 걸쳐 입력으로 주어진 그래프가 이분 그래프이면 YES, 아니면 NO를 순서대로 출력한다.
제한
- 2 ≤ K ≤ 5
- 1 ≤ V ≤ 20,000
- 1 ≤ E ≤ 200,000
예제 입력 1 복사
2
3 2
1 3
2 3
4 4
1 2
2 3
3 4
4 2
예제 출력 1 복사
YES
NO
2) 학습 풀이
- 입력 처리:
- 각 테스트 케이스마다 정점과 간선 정보를 입력받고, 인접 리스트로 그래프를 표현
- List<Integer>[] graph는 각 정점의 이웃 정점들을 저장
- 이분 그래프 판별 로직:
- isBipartite 메서드는 BFS를 사용하여 그래프를 탐색하고 색칠
- colors 배열은 각 정점의 색을 나타냅니다. 1과 -1로 두 가지 색을 구분
- 전체 그래프 탐색:
- 그래프가 연결되어 있지 않을 수 있으므로 모든 정점에서 BFS를 수행
- 색칠이 충돌하면 즉시 false를 반환하여 이분 그래프가 아님을 판단
- 출력:
- 각 테스트 케이스에 대해 "YES" 또는 "NO"를 출력합니다.
import java.io.*;
import java.util.*;
public class Main {
// BFS로 이분 그래프 판별
private static boolean isBipartite(List<Integer>[] graph, int[] colors, int start) {
Queue<Integer> queue = new LinkedList<>();
queue.add(start);
colors[start] = 1; // 시작 정점을 1로 색칠
while (!queue.isEmpty()) {
int current = queue.poll();
for (int neighbor : graph[current]) {
if (colors[neighbor] == 0) { // 이웃 정점이 아직 색칠되지 않았으면
colors[neighbor] = -colors[current]; // 다른 색으로 칠함
queue.add(neighbor);
} else if (colors[neighbor] == colors[current]) {
// 이웃 정점이 같은 색이면 이분 그래프가 아님
return false;
}
}
}
return true;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
int K = Integer.parseInt(br.readLine()); // 테스트 케이스 개수
for (int t = 0; t < K; t++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int V = Integer.parseInt(st.nextToken()); // 정점 개수
int E = Integer.parseInt(st.nextToken()); // 간선 개수
// 그래프 초기화
List<Integer>[] graph = new ArrayList[V + 1];
for (int i = 1; i <= V; i++) {
graph[i] = new ArrayList<>();
}
// 간선 정보 입력
for (int i = 0; i < E; i++) {
st = new StringTokenizer(br.readLine());
int u = Integer.parseInt(st.nextToken());
int v = Integer.parseInt(st.nextToken());
graph[u].add(v);
graph[v].add(u);
}
// 색상 배열 초기화 (0: 미방문, 1: 색1, -1: 색2)
int[] colors = new int[V + 1];
boolean isBipartite = true;
// 모든 정점에 대해 BFS 실행 (연결 그래프가 아닐 수 있으므로)
for (int i = 1; i <= V; i++) {
if (colors[i] == 0) { // 아직 방문하지 않은 정점만 탐색
if (!isBipartite(graph, colors, i)) {
isBipartite = false;
break;
}
}
}
// 결과 저장
sb.append(isBipartite ? "YES" : "NO").append("\n");
}
// 결과 출력
System.out.println(sb);
}
}
반응형
'coding_test' 카테고리의 다른 글
[99클럽 5기 코테 스터디 TIL 11일차] 체스판 다시 칠하기(feat. 완전탐색) (1) | 2025.02.03 |
---|---|
[99클럽 5기 코테 스터디 TIL 10일차] 빙산 (feat. BFS(너비 우선 탐색)) (0) | 2025.02.03 |
[99클럽 5기 코테 스터디 TIL 8일차] 단지번호붙이기(feat. 깊이 우선 탐색(DFS)) (0) | 2025.01.23 |
[99클럽 5기 코테 스터디 TIL 7일차] 숨바꼭질 (feat. 너비 우선 탐색(BFS)) (0) | 2025.01.22 |
[99클럽 5기 코테 스터디 TIL 보너스문제] 입국심사 (feat. 이분탐색) (0) | 2025.01.20 |