코딩/백준

[백준]1707번 이분 그래프 - C++

최선을 다하는 2023. 1. 17. 20:23

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

 

1707번: 이분 그래프

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

www.acmicpc.net

문제

그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있을 때, 그러한 그래프를 특별히 이분 그래프 (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

 자신이 인접한 노드가 자신과 같은 그룹이면 안된다.

아직 그룹이 설정 되지 않으면 vis [노드] = 0; 설정이 되었다면 1 혹은 -1 이 된다.

반복문을 통해 아직 그룹이 설정 되지 않은 노드들을 bfs를 통해 그룹을 만들어 준다.

그룹이 설정 되지 않은 시작 노드의 그룹을 1로 설정한다. 그다음 bfs를 통해 인접한 노드의 그룹을 정해준다.

 

인접한 노드의 그룹이 0 이면 자신과는 다른 그룹으로 설정해준다.

인접한 노드의 그룹이 0이 아닌데 자신과 그룹이 같다면 이분 그래프가 아니다.

 

추가적으로 테스트 케이스가 여러 개인 문제이므로 초기화를 주의해야 한다!

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;


int K,V,E,a,b;
int vis[20001];
bool flag;

vector <int> adj[20001];


void bfs(int x){
    queue<int> q;
    q.push(x);
    vis[x] = 1;
    while(!q.empty()){
        int cur = q.front();
        q.pop();
        for(auto i : adj[cur]){
            if(vis[i] == 0){
                vis[i] = -1 * vis[cur];
                q.push(i);
            }
            else if(vis[i] == vis[cur]){
                flag = true;
                return;
            }
        }
    }
}
int main (){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    cin >> K;
    while(K--){
        memset(vis,0,sizeof(vis));
        flag = false;
        cin >> V >> E;
        for(int i = 1 ; i <= V; i++)
            adj[i].clear();
        for(int i = 0 ; i < E ; i++){
            cin >> a >> b;
            adj[a].push_back(b);
            adj[b].push_back(a);
        }

        for(int i = 1; i <= V;i++){
            if(!vis[i]){
                bfs(i);
            }
            if(flag)
                break;
        }

        if(flag)
            cout << "NO\n";
        else cout << "YES\n";
    }
}

처음에 문제를 꼼꼼하게 읽어보지 않아 이해를 잘 못했다. 그룹이라길래 분리집합을 활용하여 풀었는데 문제가 의도하는 것이 그것이 아니었다! "인접"이기 때문에 자신의 옆 노드와 그룹이 달라야 했다. 쉽게 그룹을 왔다 갔다 하기 위해 그룹을 -1 0 1로 설정하였다. 하지만 틀렸습니다가 나왔는데 이는 초기화를 잘못해주어서 그랬다. 테스트케이스가 여러 번 나오는 문제를 오랜만에 풀어 고려하지 못했다. 

'코딩 > 백준' 카테고리의 다른 글

[백준] 2636번 치즈 - C++  (1) 2023.01.20
[백준]5639번 이진 검색 트리 - C++  (0) 2023.01.19
[백준]2146번 다리 만들기 - C++  (0) 2023.01.16
[백준]1717번 집합의표현 - C++  (0) 2023.01.13
[백준] 14890번 경사로 - C++  (0) 2023.01.12