Algorithm/BOJ

[BOJ] #1707 이분 그래프

jHoon0223 2024. 2. 25. 13:48

https://www.acmicpc.net/problem/1707

 

1707번: 이분 그래프

입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V와 간선의 개수 E가 빈 칸을 사이에

www.acmicpc.net


인접 리스트로 주어진 그래프를 보고 이분 그래프인지 아닌지 판별하면 된다. 이분 그래프에 대한 자세한 내용은 필자가 따로 정리해두었으니 해당 게시물 참조하면 된다. ⤵️

https://jhoon-study.tistory.com/89

 

[자료구조] 이분 그래프 Bipartite Graph

이분 그래프란? 인접한 정점끼리 서로 다른 두가지 집합으로만 나눈 그래프를 의미한다. 위 그림과 같이 모든 정점이 두 집합으로 나뉘고(여기서는 서로 다른 두 색상으로 구별한다.) 같은 집합

jhoon-study.tistory.com

문제는 이 이분 그래프를 C++ 코드로 어떻게 옮기는가 인데..

코드의 전체적인 매커니즘은 다음과 같다. DFS와 BFS 방식 모두 사용가능 한데, 필자는 BFS 방식을 사용했다.

 

1. 인접 리스트 형태로 그래프를 입력 받는다.

2. BFS로 그래프를 탐색하며 맨 처음 방문하는 정점을 RED라 설정하고, 이후에 탐색하는 인접한 정점들은 BLUE로 설정한다. 이때, 필자는 visited배열에서 0은 아직 방문 안한 정점 / 1은 RED / 2는 BLUE로 가정하였다.

3. RED와 BLUE가 배정된 그래프를 가지고 isBipartite 함수로 이분 그래프인지 아닌지 판별한다. 인접한 정점들을 전부 탐색하며 현재 정점과 연결된 다른 정점의 색깔이 같을 경우 그 즉시 탐색을 종료하고 false를 return한다.

4. 모든 정점들을 다 탐색했을때 같은 색끼리 인접한것이 없다면 true를 return한다.

5. isBipartite 함수의 return 값에 따라 결과값을 적절히 출력하고, 다음 테스트 케이스를 위해 clear 함수로 Graph와 visited배열을 전부 초기화해준다.

 

이분 그래프를 판별하는 법은 생각보다 어려울것은 없지만, C++ 코드로 실제로 옮기는 과정이 좀 어려웠던 것 같다. BFS를 활용한 알고리즘 중에서 대표적인 방식이니 잘 기억해두도록 하자.

#include <iostream>
#include <queue>
#include <vector>

#define MAX 200001
#define RED 1
#define BLUE 2

using namespace std;

int V,E;
vector<int> Graph[MAX];
int visited[MAX] = { 0 };

void BFS(int start) {
    queue<int> Q;
    Q.push(start);
    visited[start] = RED;

    int color = RED;
    while (!Q.empty()) {
        int curr = Q.front();
        Q.pop();

        if (visited[curr] == RED) color = BLUE;
        else if (visited[curr] == BLUE) color = RED;

        for (int i=0; i<Graph[curr].size(); i++) {
            int idx = Graph[curr][i];

            if (!visited[idx]) {
                Q.push(idx);
                visited[idx] = color;
            }
        }
    }
}

bool isBipartite() {
    for (int curr=1; curr<=V; curr++) {
        for (int j=0; j<Graph[curr].size(); j++) {
            int next = Graph[curr][j];
            
            if (visited[curr] == visited[next]) return false;
        }
    }
    return true;
}

void clear() {
    for (int i=0; i<=V; i++) {
        Graph[i].clear();
        visited[i] = 0;
    }
}

int main() {
    cin.tie();
    cout.tie();
    ios::sync_with_stdio(false);

    int K;
    cin >> K;

    while (K-->0) {
        cin >> V >> E;

        for (int i=0; i<E; i++) {
            int a,b;
            cin >> a >> b;

            Graph[a].push_back(b);
            Graph[b].push_back(a);
        }

        for (int i=1; i<=V; i++) {
            if (!visited[i]) {
                BFS(i);
            }
        }

        isBipartite() ? cout << "YES" << '\n' : cout << "NO" << '\n';

        clear();
    }

    return 0;
}

마지막 clear 함수의 범위값을 잘못 설정해서 한번 틀렸다...

 

728x90

'Algorithm > BOJ' 카테고리의 다른 글

[BOJ] #21736 헌내기는 친구가 필요해  (0) 2024.02.25
[BOJ] #1520 내리막길  (0) 2024.02.25
[BOJ] #11725 트리의 부모 찾기  (0) 2024.02.22
[BOJ] #12851 숨바꼭질 2  (0) 2024.02.21
[BOJ] #13549 숨바꼭질 3  (0) 2024.02.20