###### tags: `APCS` # **d768-Bicoloring(BFS)** ### **題目連結:** [**d768**](https://zerojudge.tw/ShowProblem?problemid=d768) ### **題目解析** 這個問題是關於圖的二分圖判定問題。二分圖是一種可以使用兩種顏色塗色,且相鄰頂點之間顏色不同的圖。問題要求判斷給定的圖是否是二分圖。 ### **解題方向** 1. 圖的建模: * 圖中的節點用編號表示,從 0 到 n-1。 * 邊的連接關係用鄰接表表示,color_map 是一個列表,列表的每個元素是一個節點所連接的所有其他節點。 1. 二分圖判定: * 使用 BFS(廣度優先搜索)來嘗試給圖中的節點塗色。 * 初始時,我們可以隨便選擇一個節點塗上一種顏色,這裡用 1 表示第一種顏色,用 2 表示第二種顏色。 * 對於每一個節點,查看它相鄰的節點。如果相鄰的節點還未塗色,就塗上與當前節點不同的顏色。如果相鄰的節點已經塗色,且顏色與當前節點相同,則該圖不是二分圖。 1. 輸出結果: * 如果 BFS 成功地塗色完成,則圖是二分圖,輸出 "BICOLORABLE."。 * 如果在塗色過程中發現某個節點和它的相鄰節點顏色相同,則圖不是二分圖,輸出 "NOT BICOLORABLE."。 ### **程式解析** 1. 初始化與讀取輸入: * 節點數 N = 3 * 邊數 M = 3 * 三條邊: * 0 -> 1 * 1 -> 2 * 2 -> 0 * 這個圖的鄰接表 (color_map) 會是: ```pyrhon color_map = [ [1, 2], # 0 接到 1 和 2 [0, 2], # 1 接到 0 和 2 [1, 0] # 2 接到 1 和 0 ] ``` 1. BFS 搜索: * 開始點:節點 0 * 初始化訪問陣列 visit 為 [0, 0, 0, ..., 0](200個0),並將 visit[0] = 1(表示節點 0 被塗為顏色1)。 1. BFS 過程: * 步驟 1: * 現在的節點:0,相鄰的節點是 1 和 2。 * 節點 1 和 2 還沒被塗色,分別塗為顏色 2(與節點0不同)。 * 將 1 和 2 加入隊列 Q。 * 此時 visit 陣列為 [1, 2, 2, ..., 0]。 * Q 為 [1, 2]。 * 步驟 2: * 現在的節點:1,相鄰的節點是 0 和 2。 * 節點 0 已經塗色,且顏色與節點 1 不同(無需處理)。 * 節點 2 已經塗色,但顏色與節點 1 相同(發現相鄰節點顏色相同,回傳 False)。 * 程式輸出 "NOT BICOLORABLE."。 ### **完整程式碼** ```python= MAX_SIZE = 200 def BFS(color_map, start): Q = [start] visit = [0 for _ in range(MAX_SIZE)] visit[start] = 1 # 初始節點塗色為1 while len(Q) > 0: now = Q.pop(0) for next_region in color_map[now]: if visit[next_region] == 0: # 下一個節點還未訪問 Q.append(next_region) visit[next_region] = 3 - visit[now] # 塗與當前節點不同的顏色 elif visit[next_region] == visit[now]: # 若相鄰節點顏色相同 return False # 無法二分塗色 return True while True: try: N = int(input()) if N == 0: break M = int(input()) color_map = [[] for _ in range(MAX_SIZE)] for _ in range(M): u, v = map(int, input().split()) color_map[u].append(v) color_map[v].append(u) result = BFS(color_map, 0) # 從第0個節點開始進行BFS if result: print("BICOLORABLE.") else: print("NOT BICOLORABLE.") except: break ```