# APCS實作題2016年3月第4題:血緣關係
> 日期:2023年6月19日
> 作者:王一哲
> 題目來源:[105年3月5日實作題第4題](https://apcs.csie.ntnu.edu.tw/wp-content/uploads/2020/10/APCS-%E5%AF%A6%E4%BD%9C%E9%A1%8C-2016.03.05.pdf)
> [ZeroJudge 單筆測資版本題目連結](https://zerojudge.tw/ShowProblem?problemid=h032)
> [ZeroJudge 多筆測資版本題目連結](https://zerojudge.tw/ShowProblem?problemid=b967)
<br />
## 題目
### 問題描述
小宇有一個大家族。有一天,他發現記錄整個家族成員和成員間血緣關係的家族族譜。小宇對於最遠的血緣關係 (我們稱之為"血緣距離") 有多遠感到很好奇。
下圖為家族的關係圖。0 是 7 的孩子,1、2 和 3 是 0 的孩子,4 和 5 是 1 的孩子,6 是 3 的孩子。我們可以輕易的發現最遠的親戚關係為 4(或 5)和 6,他們的"血緣距離"是 4 (4 ~ 1,1 ~ 0,0 ~ 3,3 ~ 6)。
給予任一家族的關係圖,請找出最遠的"血緣距離"。你可以假設只有一個人是整個家族成員的祖先,而且沒有兩個成員有同樣的小孩。
<img height="40%" width="40%" src="https://i.imgur.com/ALDTyWr.png" style="display: block; margin-left: auto; margin-right: auto;"/>
<br />
### 輸入格式
第一行為一個正整數 $n$ 代表成員的個數,每人以 $0$ ~ $n-1$ 之間惟一的編號代表。接著的
$n-1$ 行,每行有兩個以一個空白隔開的整數 $a$ 與 $b$ ($0 \leq a, b \leq n-1$),代表 $b$ 是 $a$ 的孩子。
<br />
### 輸出格式
每筆測資輸出一行最遠"血緣距離"的答案。
<br />
### 範例一:輸入
```
8
0 1
0 2
0 3
7 0
1 4
1 5
3 6
```
### 範例一:正確輸出
```
4
```
(說明)如題目所附之圖,最遠路徑為 4 → 1 → 0 → 3 → 6 或 5 → 1 → 0 → 3 → 6,距離為 4。
<img height="40%" width="40%" src="https://imgur.com/x07ATaE.png" style="display: block; margin-left: auto; margin-right: auto;"/>
<div style="text-align:center">範例一</div>
<br />
### 範例二:輸入
```
4
0 1
0 2
2 3
```
### 範例二:正確輸出
```
3
```
(說明)最遠路徑為 1 → 0 → 2 → 3,距離為 3。
<img height="23%" width="23%" src="https://imgur.com/45gYhbQ.png" style="display: block; margin-left: auto; margin-right: auto;"/>
<div style="text-align:center">範例二</div>
<br />
### 評分說明
輸入包含若干筆測試資料,每一筆測試資料的執行時間限制(time limit)均為 2 秒,依正確通過測資筆數給分。其中,
- 第 1 子題組 10 分,整個家族的祖先最多 2 個小孩,其他成員最多一個小孩,$2 \leq n \leq 100$。
- 第 2 子題組 30 分,$2 \leq n \leq 100$。
- 第 3 子題組 30 分,$101 \leq n \leq 2,000$ 。
- 第 4 子題組 30 分,$1,001 \leq n \leq 100,000$。
<br />
## Python 程式碼,單筆測資版
由參考資料1的 C++ 程式碼改寫而成,於 ZeroJudge 測試時,第18筆測資會因為遞迴深度過深被系統中止,其它筆測資可以通過測試。
```python=
md = 0
def DFS(x):
global md
max1, max2, result = 0, 0, 0
if len(F[x]) == 0: return 0
if len(F[x]) == 1: return DFS(F[x][0]) + 1
else:
for i in range(len(F[x])):
result = DFS(F[x][i]) + 1
if i == 0: max1 = result
elif i == 1:
if max1 >= result:
max2 = result
else:
max1, max2 = result, max1
else:
if max1 <= result:
max1, max2 = result, max1
elif max2 < result:
max2 = result
md = max(md, max1+max2)
return max1
n = int(input())
F = [[] for _ in range(n)]
isChild = [False]*n
for _ in range(n-1):
a, b = map(int, input().split())
F[a].append(b)
if not isChild[b]: isChild[b] = True
root = isChild.index(False)
rd = DFS(root)
md = max(rd, md)
print(md)
```
<br /><br />
## 參考資料
1. 黃建庭(2019)。**C++程式設計解題入門 融入程式設計競賽與APCS實作題(第二版)**。臺北市:碁峰資訊。
2. 吳燦銘(2020)。**APCS大學程式設計先修檢測:C++超效解題致勝祕笈**。新北市:博碩文化。
3. 溫嘉榮(2019)。**Python程式設計技巧 發展運算思維(含「APCS先修檢測」解析)**。臺北市:碁峰資訊。
4. 吳燦銘(2019)。**APCS大學程式設計先修檢測:Python超效解題致勝祕笈**。新北市:博碩文化。
---
###### tags:`APCS`、`Python`