www.acmicpc.net/problem/1707

 

1707번: 이분 그래프

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

www.acmicpc.net


  • 두 집단이 공통적으로 가지고 있는 노드가 없으면 이분 그래프라고 말할 수 있다.
  • 결국, 그래프가 여러개로 나누어져 있더라도 각 그래프들이 이분 그래프라면 전체 그래프는 이분 그래프이다.
  • 이분 그래프인지 확인하는 방법은, 한쪽 그룹의 임의 노드에서 시작하여 bfs 로 하나의 너비씩 탐색하는 것이다.
  • 한 번 반복할 때 마다 양쪽 집단을 왔다 갔다 하기 때문에, 1번째 3번째 5번째 너비는 왼쪽 그룹이고, 2번째 4번째 6번째 너비는 오른쪽 그룹이라고 생각할 수 있는 것이다.
  • 해당 그룹의 검사에서 만약 반대쪽 그룹의 노드가 포함된다면 이분 그래프가 아니다.

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

using namespace std;

int tc;
int v, e, a, b;

void cased()
{
    cin >> v >> e;
    vector<int> graph[v+1];
    vector<int> visited(v+1, -1);                               // 노드의 그룹과 방문 여부에 대한 배열. -1 이 미방문
    for(int i = 0 ; i < e ; i++)
    {
        cin >> a >> b;
        graph[a].push_back(b);
        graph[b].push_back(a);
    }

    for(int start = 1 ; start <= v ; start++)                   // 여러 개의 bipartite 그래프가 존재할 수 있기 때문에
    {                                                           // 가능한 여러 그래프들에 대해서 모두 검사함
        if(visited[start] != -1) continue;

        queue<pair<int, int>> q;                                // 방문하지 않은 점부터 시작하여 하나의 bipartite 그래프에 대해서 검사
        q.push({start, 0});

        while(q.size())
        {
            int sz = q.size();                                  // bfs 를 한번 돌 때 마다, 왼쪽과 오른쪽을 왔다갔다 한다고 보면 됨
            for(int ix = 0 ; ix < sz ; ix++)                    // 현재 큐에 들어있는 모든 노드들에 대해서
            {
                int cur = q.front().first;
                int group = q.front().second;
                q.pop();

                visited[cur] = group;                           // 현재 노드가 왼쪽 그룹인지 오른쪽 그룹인지 표시해주고
                for(int i = 0 ; i < graph[cur].size() ; i++)    // 자기가 가리키고 있는 노드들 확인
                {
                    int next = graph[cur][i];
                    if(visited[next] == group)                  // 만약 내가 가리키고 있는 노드들 중 나와 같은 그룹이 있다면
                    {                                           // 해당 노드는 왼쪽 그룹과 오른쪽 그룹에 모두 포함되어있다는 뜻이기 떄문에
                        cout << "NO" << endl;                   // 이분그래프 불가능
                        return;
                    }
                    if(visited[next] == -1) q.push({next, (group + 1) % 2});
                }
            }
        }
    }

    cout << "YES" << endl;                                      // 전체 그래프 안의 모든 그래프들이 이분그래프라면, 두 개로 나눌 수 있음
}

int main(void)
{
    cin >> tc;
    while(tc--) cased();
}

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

[백준] 16928 : 뱀과 사다리 게임  (0) 2021.05.01
[백준] 11659 : 구간 합 구하기 4  (0) 2021.04.30
[백준] 2583 : 영역 구하기  (0) 2021.04.12
[백준] 14938 : 서강그라운드  (0) 2021.04.10
[백준] 1941 : 소문난 칠공주  (0) 2021.04.07

+ Recent posts