For Programmer
백준 1707번 파이썬 문제풀이(큐와 그래프 - 이분 그래프) - DFS, BFS 본문
728x90
이 문제는 개인적으로 상당히 어려웠다. 사실 이문제는 간단한 규칙하나만 알면된다. 각 정점(노드)들을 이웃 꼭짓점들과 다른 색으로 계속해서 칠해 나가면서, 같은 색깔의 꼭짓점이 서로 연결되어 있는 모순이 발생하는지 여부를 확인하면 된다. 하지만 이러한 풀이방식을 처음부터 생각해 내기란 쉽지는 않다.
1. DFS
import sys
sys.setrecursionlimit(1000000)
input = sys.stdin.readline
K = int(input())
def dfs(start, group):
visited[start] = group # 해당 정점의 group 설정(1,-1)
for i in graph[start]:
if not visited[i]: # 만약 방문하지 않았다면
a = dfs(i, -group) # 그룹값을 -1로 주어 dfs를 돈다.
if not a: # 만약 a가 false가 나왔다면
return False # False를 리턴
elif visited[i] == visited[start]: # 만약 현재 정점과 연결된 정점의 그룹값이 같다면
return False # False를 리턴
return True # 그외의 경우는 True를 리턴
for _ in range(K):
V, E = map(int, input().split())
graph = [[] for _ in range(V + 1)] # 빈 그래프 생성
visited = [False] * (V + 1) # 방문한 정점 체크
for _ in range(E):
a, b = map(int, input().split())
graph[a].append(b)
graph[b].append(a)
for i in range(1, V + 1):
if not visited[i]: # 방문한 정점이 아니면, dfs 수행
result = dfs(i, 1)
if not result: # 만약 result가 False가 나왔다면 더이상 수행할 필요가 없으므로
break # break
print("YES" if result else "NO")
2. 위의 DFS를 조금더 쉽게 표현
import sys
sys.setrecursionlimit(20000)
input = sys.stdin.readline
def dfs(start, group):
global error
# 만약 사이클이 true라면 재귀탈출
if error:
return
visited[start] = group # 해당 그룹으로 등록
for i in graph[start]:
if not visited[i]:
dfs(i, -group) # 다른 그룹으로 설정
elif visited[start] == visited[i]: # 인접한데 같은 그룹이라면
error = True # 에러값 True
return # 그후 재귀 리턴
T = int(input())
for _ in range(T):
V, E = map(int, input().split())
graph = [[] for _ in range(V + 1)] # 빈 그래프 생성
visited = [False] * (V + 1) # 방문한 정점 체크
error = False
for _ in range(E):
a, b = map(int, input().split())
graph[a].append(b)
graph[b].append(a)
for i in range(1, V + 1):
if not visited[i]: # 만약 아직 방문하지 않았다면
dfs(i, 1) # dfs를 돈다.
if error: # 만약 에러가 참이라면
break # 탈출
if error:
print('NO')
else:
print('YES')
2.BFS
import sys
from collections import deque
input = sys.stdin.readline
# bfs
def bfs(start, group):
queue = deque([start]) # 시작 정점 값을 큐에 담는다.
visited[start] = group # 시작 정점 그룹을 설정
while queue: # 큐가 존재할때까지 돈다.
x = queue.popleft() # 큐의 맨앞 원소를 빼낸다.
for i in graph[x]: # 해당 정점에서 갈 수 있는 하위 정점들을 돈다.
if not visited[i]: # 만약 그 정점들을 아직 방문하지 않았다면
queue.append(i) # 그 정점들을 추가하고
visited[i] = -1 * visited[x] # 상위 정점과 다른 그룹으로 편성
elif visited[i] == visited[x]: # 만약 정점들을 이미 방문했었는데 같은 그룹이라면
return False # False를 바로 리턴
return True # 위의 조건에 걸리지 않았다면 True를 리턴
for _ in range(int(input())):
V, E = map(int, input().split())
graph = [[] for i in range(V + 1)] # 빈 그래프 생성
visited = [False] * (V + 1) # 방문한 정점 체크
for _ in range(E):
a, b = map(int, input().split())
graph[a].append(b) # 무방향 그래프
graph[b].append(a) # 무방향 그래프
for i in range(1, V + 1):
if not visited[i]: # 방문한 정점이 아니면, bfs 수행
result = bfs(i, 1)
if not result:
break
print('YES' if result else 'NO')
728x90
'코팅테스트 > 백준 문제 모음' 카테고리의 다른 글
백준 2178번 파이썬 문제풀이(큐와 그래프 - 미로탐색) - BFS (0) | 2021.11.22 |
---|---|
백준 2667번 파이썬 문제풀이(큐와 그래프 - 단지번호붙이기) - DFS, BFS (0) | 2021.11.21 |
백준 11724번 파이썬 문제풀이(큐와 그래프 - 연결 요소의 개수) - DFS, BFS (0) | 2021.11.19 |
백준 1260번 파이썬 문제풀이(큐와 그래프 - DFS와 BFS) (0) | 2021.11.17 |
백준 13023번 파이썬 문제풀이(큐와 그래프 - ABCDE) (0) | 2021.11.15 |
Comments