출처 : 1707번: 이분 그래프 (acmicpc.net)
이분 그래프 성공 분류
시간제한 메모리 제한 제출 정답 맞은 사람 정답 비율
2 초 | 256 MB | 39600 | 10147 | 5871 | 23.141% |
문제
그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있을 때, 그러한 그래프를 특별히 이분 그래프 (Bipartite Graph) 라 부른다.
그래프가 입력으로 주어졌을 때, 이 그래프가 이분 그래프인지 아닌지 판별하는 프로그램을 작성하시오.
입력
입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K(2≤K≤5)가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V(1≤V≤20,000)와 간선의 개수 E(1≤E≤200,000)가 빈칸을 사이에 두고 순서대로 주어진다. 각 정점에는 1부터 V까지 차례로 번호가 붙어 있다. 이어서 둘째 줄부터 E개의 줄에 걸쳐 간선에 대한 정보가 주어지는데, 각 줄에 인접한 두 정점의 번호가 빈칸을 사이에 두고 주어진다.
출력
K개의 줄에 걸쳐 입력으로 주어진 그래프가 이분 그래프이면 YES, 아니면 NO를 순서대로 출력한다.
[ 문제 설명 ]
이 문제를 이해하기 위해서는 이분 그래프라는 개념을 이해해야 문제를 풀 수 있다. 이 문제를 처음 맞닥뜨리면 사뭇 이게 먼 소리고? 멀 구하라는 건지 모를 수 있다.
그 이유는 이분 그래프를 몰라서인데 이분 그래프를 알아보자!
- 정의를 먼저 보자 -
인접한 정점끼리 서로 다른 색으로 칠해서 모든 정점을 두 가지 색으로만 칠할 수 있는 그래프를 말한다.
즉, 그래프의 모든 정점이 두 그룹으로 나눠지고 서로 다른 그룹의 정점이 간선으로 연결된 그래프를 이분 그래프라고 한다. (여기서 중요한 점은 같은 그룹에 속한 정점끼리는 서로 인접하지 않도록 해야 한다. 이는 간선이 존재하지 않음을 의미한다.)
그림으로 설명을 돕겠습니다.
이런 식으로 색깔 있는 정점에 의해 구분되는 그래프가 이분 그래프이고, 저는 파랑을 1 레드를 2라고 놔서 코딩으로서 구분해보겠습니다
[ 코드 ]
import sys
from collections import deque
def BFS(st):
q = deque()
q.append(st) # 아까 DFS함수를 돌면서 visited리스트의 인덱스값을 모두 1로 바꾸어 주었던 상태이므로 1인상태가 방문을 안한상태이니까 방문을 했을 경우 0으로 바꾸어준다.
visitedList[st] = 1
while q:
N = q.popleft()
# print(q, end=' ')
for index in connected[N]:
if visitedList[index] == -1: # 배정 x
if visitedList[N] == 1: # 파랑
visitedList[index] = 2 # 파랑이 있으면 옆에는 빨강
elif visitedList[N] == 2: # 빨강이면~
visitedList[index] = 1 # 옆에는 파랑~
q.append(index)
elif visitedList[index] == visitedList[N]: # 인접한 부분이 같으면 이분 그래프가 아니다.
return 0
return 1
# print(result)
testCase = int(sys.stdin.readline())
for _ in range(testCase):
N, M = map(int, sys.stdin.readline().split())
connected = [set() for _ in range(N + 1)]
#print("connect:", connected)
for _ in range(M):
a, b = map(int, sys.stdin.readline().split())
connected[a].add(b)
connected[b].add(a)
print("connect1:", connected)
visitedList = [-1] * (N + 1) # matrix
flag = True
for q in range(1, N + 1):
if visitedList[q] == -1:
tmp = BFS(q)
if not tmp:
print(q)
flag = False
break
if flag:
print("YES")
else:
print("NO")
설명을 이해한 후 코드를 본인의 환경 내에서 한 줄 한 줄 치시면서 음미해보시면 이해가 되실 겁니다.
안되시면 제가 #해둔 부분의 코드 부분을 풀어서 흐름을 확인해 보세요
후기
그래프 문제는 접근법이 다른 문제랑 달라서 신선하고 재밌습니다.
'백준 코딩 테스트' 카테고리의 다른 글
백준 1002번 - 터렛 (0) | 2021.02.18 |
---|---|
백준 10451번 순열 사이클 (0) | 2021.02.15 |
백준 - 11724번 연결 요소의 개수 (0) | 2021.02.14 |
백준 - 1260번 DFS와 BFS (0) | 2021.02.14 |
백준 - 11054번 가장 긴 바이토닉 부분 수 (0) | 2021.02.12 |