백준 이분 그래프 [c++]
이분 그래프 골드4
문제
그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있을 때, 그러한 그래프를 특별히 이분 그래프 (Bipartite Graph) 라 부른다.
그래프가 입력으로 주어졌을 때, 이 그래프가 이분 그래프인지 아닌지 판별하는 프로그램을 작성하시오.
입력
입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V와 간선의 개수 E가 빈 칸을 사이에 두고 순서대로 주어진다. 각 정점에는 1부터 V까지 차례로 번호가 붙어 있다. 이어서 둘째 줄부터 E개의 줄에 걸쳐 간선에 대한 정보가 주어지는데, 각 줄에 인접한 두 정점의 번호 u, v (u ≠ v)가 빈 칸을 사이에 두고 주어진다.
출력
K개의 줄에 걸쳐 입력으로 주어진 그래프가 이분 그래프이면 YES, 아니면 NO를 순서대로 출력한다.
풀이
- 이분그래프 : 인접한 정점끼리 서로 다른 색으로 칠해서 모든 정점을 두 가지 색으로만 칠할 수 있는 그래프. https://gmlwjd9405.github.io/2018/08/23/algorithm-bipartite-graph.html
- 인접한 정점은 같은 색으로 칠해지면 안된다.
- BFS로 같은 레벨은 같은 색으로 칠한다. 그리고 다 칠하고 나서 인접한 정점에 같은 색으로 칠해진 것이 있는지 확인.
- 색을 칠하는 state_change함수와 bipartite인지 확인하는 is_bipartite함수를 작성하여 해결.
코드
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
vector<int> graph[20001];
queue<int> q;
int visited[20001];
void init(){
for(int i = 0; i < 20001; i++)
{
visited[i] = 0;
graph[i].clear();
}
}
int state_change(int state){
if(state == 1) return 2;
if(state == 2) return 1;
}
void bfs(int start){
int state = 1;
visited[start] = state;
int size = graph[start].size();
for(int i = 0; i < size; i++)
{
q.push(graph[start][i]);
}
while(!q.empty()){
int q_size = q.size();
state = state_change(state);
for(int i = 0; i < q_size; i++)
{
if(visited[q.front()] == 0){
visited[q.front()] = state;
for(int j = 0; j < graph[q.front()].size(); j++)
{
if(visited[graph[q.front()][j]] == 0)
{
q.push(graph[q.front()][j]);
}
}
}
q.pop();
}
}
// return 1;
}
int is_bipartite(int v){
for(int i = 1; i <= v; i++)
{
int size = graph[i].size();
for(int j = 0; j < size; j++)
{
if(visited[i] == visited[graph[i][j]]){
return 0;
}
}
}
return 1;
}
int main(){
int k;
cin >> k;
for(int i = 0; i < k; i++)
{
int v, e;
cin >> v >> e;
int f, t;
init();
for(int j = 0; j < e; j++)
{
cin >> f >> t;
graph[f].push_back(t);
graph[t].push_back(f);
}
for(int k = 1; k <= v; k++)
{
if(visited[k] == 0){
bfs(k);
}
}
if(is_bipartite(v)){
cout << "YES" << endl;
} else{
cout << "NO" << endl;
}
}
return 0;
}