Graph - 이분 그래프
이분 그래프란?
- 그래프를 위의 그림처럼 왼쪽과 오른쪽(A와 B)으로 나눌 수 있는 그래프.
- 왼쪽에 포함된 정점끼리 연결 된 간선이 없고, 오른쪽에 포함된 정점끼리 연결 된 간선이 없다.
- 쉽게 말해서 편 가르기 다.
이분 그래프 찾아내기
-
DFS와 BFS를 이용한다.
- 정점을 방문 할 때 마다 __번갈아__가면서 분홍색과 보라색을 칠한다고 했을 때, 이분 그래프라면 6번의 그림처럼 완벽히 분홍색인 부분과 보라색인 부분으로 나뉘어진다.
- 서로 연결된 정점끼리는 다른 색을 가지고 있다.
하지만, 이분 그래프가 아니라면
- 6번의 상황을 보자면 정점 6번에서 더 이상 갈 수 있는 곳이 있는지 확인한다.
- 이때, 정점 6번에 연결된 정점은 3번과 2번인데, 둘 다 이미 방문한 적이 있는 곳이다. 그래서 더 이상 방문을 진행하지 않는다.
- 색을 확인 해보면(이분 그래프는 방문하지 않아도 색 확인이 가능하다) 정점 3이 정점 6과 색이 같은 것을 알 수 있다. 따라서, 연결된 정점이 같은 색을 가지고 있으므로 이분 그래프가 아니다.
이분그래프 문제
-
문제
-
풀이
-
dfs 함수 부분
1234567891011121314151617bool dfs(int v, int c) {color[v] = c;for (int i = 0; i < list[v].size(); i++) {int next = list[v][i];if (color[next] == 0) {if (!dfs(next, 3 - c)) {return false;}}else if (c == color[next]) {return false;}}return true;}cs - 방문 여부를 파악하기 위해 bool 값을 가지는 check라는 배열을 둔 것이 아닌 color라는 배열을 사용했다.
- color의 값이 0 : 방문 x
- color의 값이 1 : group1
- color의 값이 2 : group2
- 3-c를 사용한 이유는, color의 값을 구분하기 위해 사용한 1과 2의 합이 3이기 때문이다.
- 현재 정점이 group1에 속한 경우에 다음 정점은 group2에 속해야 하기 때문에 3-1의 값인 2가 color에 저장된다.
-
main 함수 부분
12345678910111213141516171819202122232425262728293031323334353637int main() {int test;scanf("%d", &test);while (test--) {memset(list, 0, sizeof(list));memset(color, 0, sizeof(color));int v, e;scanf("%d %d", &v, &e);int n, m;for (int i = 0; i < e; i++) {scanf("%d %d", &n, &m);list[n].push_back(m);list[m].push_back(n);}bool ok = true;for (int i = 1; i <= n; i++) {if (color[i] == 0) {if (dfs(i, 1) == false) {ok = false;}}}printf("%s\n", ok ? "YES" : "NO");}return 0;}cs - 32 : 출력에는 3항 연산자를 이용했다.
가능한 실수- 처음에는 24~32 말고
위의 코드로 작성했다.1dfs(1,1) ? printf("YES\n") : printf("NO\n");cs
하지만 문제에서 제시한 예시는 정상적인 출력을 보였으나, 답안을 제출한 결과는 '틀렸습니다' 였다.
테스트 케이스 중에 연결 요소가 하나가 아닌 그래프가 있는 것 같아서(연결 요소에 대한 설명은 여기서) 새로운 연결 요소에서도 탐색을 시작 할 수 있도록 코드를 작성하여 제출했더니 통과되었다.-
전체 코드
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465#include <cstdio>#include <vector>#include <cstring>using namespace std;vector<int> list[20001];int color[20001];bool dfs(int v, int c) {color[v] = c;for (int i = 0; i < list[v].size(); i++) {int next = list[v][i];if (color[next] == 0) {if (!dfs(next, 3 - c)) {return false;}}else if (c == color[next]) {return false;}}return true;}int main() {int test;scanf("%d", &test);while (test--) {memset(list, 0, sizeof(list));memset(color, 0, sizeof(color));int v, e;scanf("%d %d", &v, &e);int n, m;for (int i = 0; i < e; i++) {scanf("%d %d", &n, &m);list[n].push_back(m);list[m].push_back(n);}//dfs(1,1) ? printf("YES\n") : printf("NO\n");bool ok = true;for (int i = 1; i <= n; i++) {if (color[i] == 0) {if (dfs(i, 1) == false) {ok = false;}}}printf("%s\n", ok ? "YES" : "NO");}return 0;}cs
-
아직 배움의 과정에 있는 학생이니 내용에 부족한 점이 보이면 지적은 하되, 비난은 하지 말아주세요!!
댓글남기기