본문 바로가기

백준 코딩 테스트

백준 1707번 이분그래프

728x90

출처 : 1707번: 이분 그래프 (acmicpc.net)

 

1707번: 이분 그래프

입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K(2≤K≤5)가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V(1≤V≤20,000)와 간선의 개수

www.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 - 이분 그래프 설명

 

이런 식으로 색깔 있는 정점에 의해 구분되는 그래프가 이분 그래프이고, 저는 파랑을 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")

설명을 이해한 후 코드를 본인의 환경 내에서 한 줄 한 줄 치시면서 음미해보시면 이해가 되실 겁니다.

안되시면 제가 #해둔 부분의 코드 부분을 풀어서 흐름을 확인해 보세요

 


후기

 

그래프 문제는 접근법이 다른 문제랑 달라서 신선하고 재밌습니다.

 

728x90