https://www.acmicpc.net/problem/1707
1707번: 이분 그래프
입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K(2≤K≤5)가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V(1≤V≤20,000)와 간선의 개수
www.acmicpc.net
문제
그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있을 때, 그러한 그래프를 특별히 이분 그래프 (Bipartite Graph) 라 부른다.
그래프가 입력으로 주어졌을 때, 이 그래프가 이분 그래프인지 아닌지 판별하는 프로그램을 작성하시오.
입력
입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K(2≤K≤5)가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V(1≤V≤20,000)와 간선의 개수 E(1≤E≤200,000)가 빈 칸을 사이에 두고 순서대로 주어진다. 각 정점에는 1부터 V까지 차례로 번호가 붙어 있다. 이어서 둘째 줄부터 E개의 줄에 걸쳐 간선에 대한 정보가 주어지는데, 각 줄에 인접한 두 정점의 번호가 빈 칸을 사이에 두고 주어진다.
출력
K개의 줄에 걸쳐 입력으로 주어진 그래프가 이분 그래프이면 YES, 아니면 NO를 순서대로 출력한다.
접근방식 및 고려사항
- BFS 로 해결가능하다.
- 이분 그래프의 특성상 BFS를 진행하면서 0과 1을 번갈아 가면서 체크해준다.
- 체크하는 과정에서 만약 인접한 노드가 현재노드의 체크값과 같으면 이분그래프가 아닌것이다.
- 주어진 인풋이 완전한 하나의 그래프가 아닐수도 있으므로 모든 정점에 대해 탐색하면서 방문하지 않은 노드들에 대해서 모두 bfs를 시행해야 한다.
- 한번 이분그래프가 아니라는 결과가 도출되었으면 다음탐색하는 그래프가 이분그래프인지 여부와 상관없이 NO를 출력해야 한다. 이부분을 처음에 고려하지 못했다.
#include <iostream>
#include <queue>
#include <vector>
#define vMAX 20005 // 범위설정 잘못함 20000 -> 20001
using namespace std;
int check[vMAX];
bool bfs(int start, vector<int> a[]){
queue<pair<int, int>> q;
bool result = true;
q.push({start, 1});
check[start]=1;
while(!q.empty()){
int x = q.front().first;
int cnt = q.front().second;
int ch = check[x];
q.pop();
for(int i=0; i<a[x].size(); i++){
int c = a[x][i];
if(check[c]==ch) result = false;
if(check[c]==-1){
check[c] = (cnt+1)%2;
q.push({c,cnt+1});
}
//printf("x:%d, ch:%d, check[%d]:%d\n", x,ch,c,check[c]);
}
}
return result;
}
int main()
{
int t; cin >> t;
for(int k=0; k<t; k++){
int v,e; cin >> v >> e;
vector<int> a[vMAX];
bool result=true;
for(int x,y,i=0; i<e; i++){
cin >> x >> y;
a[x].push_back(y);
a[y].push_back(x);
}
for(int i=1; i<=vMAX; i++)
check[i]=-1;
for(int i=1; i<=v; i++){ // 1부터 시작해서 v와 같을때 까지 해야하는데 범위 설정을 잘못해서 오답이 나왔음.
// + 이미 한번 false인 상황이면 이를 고정시켜야 하는데 result = bfs()로 해서 마지막 bfs가 답으로 출력되는 상황이 되었었음.
//printf("%d\n",i);
if(check[i]==-1){
if(bfs(i, a)==false)
result = false;
//printf("%d번째 - in : %d\n",k+1,i);
}
}
if(result==false){
printf("NO\n");
}else{
printf("YES\n");
}
}
return 0;
}
느낀점
배열 인덱스 설정하는 부분과 한번 이분그래프 판정이 났으면 답을 유지해야 하는 부분 등 세밀한 것들을 자꾸 놓치게 된다. 문제조건과 생각을 더 꼼꼼하게 체크할 필요가 있다고 느꼈다.
'알고리즘 문제풀이' 카테고리의 다른 글
[백준] 1504번 특정한 최단 경로 c++ (0) | 2021.07.19 |
---|---|
[백준] 7569번 토마토 c++ (0) | 2021.07.14 |
[백준] 2206번 벽 부수고 이동하기 c++ (0) | 2021.07.13 |
[백준] 7562번 나이트의 이동 c++ (0) | 2021.07.12 |
[백준] 2240번 자두나무 c++ (0) | 2021.07.08 |