Notion에서 작성한 글이라, 여기에서 더 깔끔하게 보실 수 있습니다! 😮😊
문제를 읽으며 메모한 내용
‘심지어 두 플레이어가 서로의 위치를 알고 일부러 게임을 끝내려고 해도 끝낼 수 없다!’ 라는 문제의 설명이 풀이를 생각해내는 데에 정말 큰 도움이 되었다. 그리고 한 편으론 뭔가 너무 안타까웠다. 만나고 싶어도 만날 수가 없는 사이라니… 갑자기 감성에 잠깐 젖었었다,,, 😢 요새 좀 T가 되어가는 줄 알았는데 아직 멀었나 보다.
사실 바로 감이 오질 않아서 예제들의 그래프를 직접 그려보면서 생각했다. 어느 상황에서 둘은 만나고 싶어도 못 만나는지를 살펴보니, 크게 세 가지 경우로 나눌 수 있었다. (설명의 편의상 ‘어떻게 움직여도 영원히 게임이 끝나는/끝나지 않는’을 ‘게임이 끝나는/끝나지 않는’으로 줄여서 작성하겠다!)
두 정점 사이의 최단거리가 짝수라면 게임이 끝난다는 점은 직관적으로 이해하기 쉽다. 중요한 것은 게임을 끝낼 수 있는지의 여부기 때문에, 복잡한 경우를 생각할 것 없이 당장 최단거리로 만나버리면 게임을 끝낼 수 있다.
홀수일 경우엔, 삼각형과 사각형 형태의 그래프를 그려놓고 생각하면 쉽다.
위와 같이 단순한 형태의 그래프면 구하기 쉽지만, 복잡한 형태의 그래프에서 수없이 많은 cycle이 있을텐데 이걸 어떻게 하나하나 다 체크하지…? 어떻게 체크해낸다고 해도 정점과 간선의 수가 많아서 제한시간 내에는 처리할 수 없어보였다. 게다가 두 정점들 사이의 거리는 각각 모두 계산해주어야 하나? ?? 제한시간 내에는 절대 불가능해보였다.
삼각형 모양의 그림을 통해 천천히 생각해 보았다. 임의의 정점부터 시작하여 다른 정점들 사이의 거리를 구하기 위한 BFS를 돌린다.
이를 종합하면 위에서 막막했던 부분들이 풀린다.
import sys
input = sys.stdin.readline
from collections import deque
def bfs(v):
queue = deque([v])
visited = [False]*(n+1)
visited[v] = True
distance = [0]*(n+1)
odds = 0
evens = 1
while queue:
cur = queue.popleft()
for nxt in adj[cur]:
if not visited[nxt]:
visited[nxt] = True
distance[nxt] = distance[cur]+1
if distance[nxt]%2: odds += 1
else: evens += 1
queue.append(nxt)
elif distance[nxt]%2 != (distance[cur]+1)%2: return 0
return odds*evens*2
n, m = map(int, input().split())
adj = [[] for _ in range(n+1)]
for _ in range(m):
u, v = map(int, input().split())
adj[u].append(v)
adj[v].append(u)
print(bfs(1))
evens
는 1로 시작한다.import sys
input = sys.stdin.readline
from collections import deque
def bfs(v):
queue = deque([v])
state = [None] * (n+1)
state[v] = False
evens = 1
while queue:
cur = queue.popleft()
for nxt in adj[cur]:
if state[nxt] is None:
state[nxt] = not state[cur]
if not state[nxt]: evens += 1
queue.append(nxt)
elif state[nxt] == state[cur]: return 0
return evens*(n-evens)*2
n, m = map(int, input().split())
adj = [[] for _ in range(n+1)]
for _ in range(m):
u, v = map(int, input().split())
adj[u].append(v)
adj[v].append(u)
print(bfs(1))
True
/ False
로 관리할 수 있겠다고 생각했다.visited
또한 None
으로 처리하면 방문 여부 체크와 최단거리 체크까지 한 번에 묶어서 할 수 있겠다는 생각이 들었다.True
/ False
를 반전시키지 않고 현재의 홀짝성만 체크해주어도 된다.Memo