###### tags: `APCS`
# **a290-新手訓練系列 ~ 圖論**
### **題目連結:** [**a290**](https://zerojudge.tw/ShowProblem?problemid=a290)
### **題目解析**
這個題目要求我們判斷從城市 A 是否能夠到達城市 B。這可以轉換成圖論中的「尋找從節點 A 到節點 B 是否存在路徑」問題。由於道路是有方向性的,因此我們要考慮有向圖。
### **解題方向**
* 將每個城市視為圖中的一個節點,每條道路則是一條有方向性的邊。
* 我們可以利用 廣度優先搜尋(BFS) 來檢查從節點 A 是否可以到達節點 B。
* 初始化時,我們將 A 作為起點,並標記它已被訪問,接著遍歷與 A 相鄰的所有節點,直到找到節點 B 或遍歷所有可能路徑為止。
### **程式解析**
1. 資料結構:
* 使用一個列表 G 來儲存每個城市可以到達的鄰接城市。例如,G[u] 代表從城市 u 出發的所有目的地城市的列表。
1. 讀取輸入:
* 首先讀取 N 和 M,表示城市數量和道路數量。
* 接著讀取每條道路的起點和終點,並更新 G 以儲存鄰接資訊。
* 最後讀取要檢查的兩個城市 A 和 B。
1. 廣度優先搜尋(BFS):
* 使用 route 列表來存放下一個要訪問的城市,並且使用 visit 列表來標記已經訪問過的城市。
* 不斷從 route 中取出當前城市,並檢查它可以到達的所有城市,如果這些城市未被訪問過,則將其加入 route。
1. 判斷結果:
* 如果在搜尋過程中,城市 B 被訪問到,則說明存在從 A 到 B 的路徑,輸出 "Yes!!!"。
* 否則,輸出 "No!!!"。
### **完整程式碼**
```python=
import sys
# 使用 sys.stdin 來讀取多筆輸入資料
for s in sys.stdin:
N, M = map(int, s.split())
G = [[] for i in range(N + 1)] # 鄰接列表
for i in range(M):
u, v = map(int, input().split())
G[u].append(v) # 將道路加入圖中
A, B = map(int, input().split())
route = [A] # 開始點
visit = [0 for i in range(N + 1)] # 訪問標記
# BFS
while len(route) > 0:
now = route.pop(0)
visit[now] = 1
for next_city in G[now]:
if visit[next_city] == 0:
visit[next_city] = 1
route.append(next_city)
if visit[B] == 1:
print("Yes!!!")
else:
print("No!!!")
```
改用sys.stdin.readline()
```python=
import sys
#start
for s in sys.stdin:
N, M = map(int, s.split())
G = [ [] for i in range(N+1) ]
for i in range(M):
u, v = map(int, sys.stdin.readline().split())
G[u].append(v)
A, B = map(int, sys.stdin.readline().split())
route = [A]
visit = [ 0 for i in range(N+1) ]
while len(route)>0:
now = route.pop(0)
visit[now] = 1
for next_city in G[now]:
if visit[next_city] == 0:
visit[next_city] = 1
route.append(next_city)
if visit[B] == 1:
print("Yes!!!")
else:
print("No!!!")
```
### **範例解析**
* 輸入範例 #1:
* 城市 1 到城市 3 有兩條直接道路。
* 輸出 "Yes!!!" 因為 A 城市可以到達 B 城市。