본문 바로가기
알고리즘/백준

[Java] BOJ 1707번 이분 그래프

by 컴공맨 2021. 7. 25.
 

1707번: 이분 그래프

입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K(2≤K≤5)가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V(1≤V≤20,000)와 간선의 개수

www.acmicpc.net


풀이

DFS와 BFS를 사용해서 해결했습니다.

자세한 건 코드의 주석을 참고해주세요.


코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
	public static int K, V, E;
	public static int[] visited;
	public static List<Integer>[] tree;
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder("");
		StringTokenizer st = null;
		
		K = Integer.parseInt(br.readLine());
		
		while (K-- > 0) {
			st = new StringTokenizer(br.readLine(), " ");
			
			V = Integer.parseInt(st.nextToken());
			E = Integer.parseInt(st.nextToken());
			
			visited = new int[V + 1];
			tree = new ArrayList[V + 1];
			
			for (int i = 1; i <= V; ++i) {
				tree[i] = new ArrayList<Integer>();
			}
			
			for (int i = 0; i < E; ++i) {
				st = new StringTokenizer(br.readLine(), " ");
				
				int from = Integer.parseInt(st.nextToken());
				int to = Integer.parseInt(st.nextToken());
				
				tree[from].add(to);
				tree[to].add(from);
			}
			
			boolean flag = true;
			// 입력으로 연결이 안된 그래프도 주어질 수 있으므로
			// 모든 점을 검사하며 방문하지 않은점을 모두 탐색하도록 한다.
			for (int i = 1; i <= V; ++i) {
				if (visited[i] == 0) {
					// flag = dfs(i, 1);	// dfs 방식
					flag = bfs(i);			// bfs 방식
				}
				
				// flag가 false이면 이는 이분그래프가 아닌 그래프라는 의미이므로
				// 문제에 의해 더이상 조사를 하지 않아도 되므로 break를 수행한다.
				if (!flag) {
					break;
				}
			}
			
			sb.append((flag) ? "YES\n" : "NO\n");
		}
		
		System.out.println(sb);
	}
	
	// 그룹을 1과 -1로 나눔
	public static boolean dfs(int cur, int group) {
		visited[cur] = group;
		
		for (int next : tree[cur]) {
			// 방문한적이 없다면
			if (visited[next] == 0) {
				// 방문하면서 return값이 false이면 false를 반환하도록 하고
				// true일 경우는 다음 정점도 검색을 하기위해 return을 통해 반환을 시키면 안된다.
				if (dfs(next, -group) == false) {
					return false;
				}
			}
			
			// 위에 if문에서 return을 처리하므로 자동적으로 방문하지 않을 경우가 되고
			// 또한, 현재 정점과 다음 정점의 group이 같다면 이는 이분그래프가 아니므로 false를 반환
			if (visited[next] == visited[cur]) {
				return false;
			}
		}
		
		// for문을 정상적으로 수행했다면 이분그래프이므로 true를 반환
		return true;
	}
	
	public static boolean bfs(int i) {
		Queue<Integer> q = new LinkedList<Integer>();
		q.offer(i);
		visited[i] = 1;
		
		while (!q.isEmpty()) {
			int cur = q.poll();
			
			for (int next : tree[cur]) {
				// 방문하지않은 점이라면 bfs 수행
				if (visited[next] == 0) {
					q.offer(next);
					// 그룹은 1, -1로 나눔
					visited[next] = -visited[cur];
				}
				else if (visited[next] == visited[cur]) {
					// 만약 방문한 점이면서 현재 정점과 같은 그룹이라면
					// 이분그래프가 될 수 없으므로 false를 반환
					return false;
				}
			}
		}
		
		// 모든 bfs과정을 성공적으로 끝냈다면 이는 이분 그래프이므로 true를 반환
		return true;
	}
}

 

GitHub - pyo7410/Algorithm: 1일 1커밋을 목표로!

1일 1커밋을 목표로! Contribute to pyo7410/Algorithm development by creating an account on GitHub.

github.com

 

'알고리즘 > 백준' 카테고리의 다른 글

[Java] BOJ 2573번 빙산  (0) 2021.08.02
[Java] BOJ 1261번 알고스팟  (0) 2021.07.30
[Java] BOJ 11404번 플로이드  (0) 2021.07.24
[Java] BOJ 1520번 내리막 길  (0) 2021.07.23
[Java] BOJ 1717번 집합의 표현  (0) 2021.07.21