# 資料結構題 - 樹狀圖分析 - APCS - by Peter Wang ## 題目資訊 此題為2017.10.18 測驗中的題目3 ###### tags: `APCS` `Tree` `DFS` ## Rooted Tree定義 在一棵 *n* 個節點的有根樹中,每個節點都是以 *1~n* 的不同數字來編號,描述一棵有根樹必須定義節點與節點之間的親子關係。一棵有根樹恰有一個節點沒有父節點(parent),此節點被稱為根節點(root),除了根節點以外的每一個節點都恰有一個父節點,而每個節點被稱為是它父節點的子節點(child),有些節點沒有子節點,這些節點稱為葉節點(leaf)。在當有根樹只有一個節點時,這個節點既是根節點同時也是葉節點。在圖形表示上,我們將父節點畫在子節點之上,中間畫一條邊(edge)連結。例如:下圖中表示的是一棵 9 個節點的有根樹,其中,節點 1 為節點 6 的父節點,而節點 6 為點 1 的子節點;又 5 、 3 與 8 都是 2 的子節點。節點 4 有父節點,所以節點 4 是根節點;而 6 、 9 、 3 與 8 都是葉節點。 ![](https://i.imgur.com/ciA0Iav.png) ## DFS概述 如下圖由 4 開始走訪按照數字順序依序 DFS ,這也是基本 DFS 圖像化的概念。 ![](https://i.imgur.com/W7DvCdl.png) 當然 DFS 還有分成不同種走訪方式這裡就先不多做解釋。 ## 題目敘述 樹狀圖中的兩個節點 *u* 和 *v* 之間的距離 *d ( u , v )* 定義為兩節點之間邊的數量。如上圖中:*d ( 7 , 5 ) = 2* ,而 *d ( 1 , 2 ) = 3*。對於樹狀圖中的節點點 *v* ,我們以 *h(v)* 代表節點 *v* 的高度,其定義是節點 *v* 和節點 *v* 下面最遠的葉節點之間的距離,而葉節點的高度定義為 *0* 。如上圖中,節點 6 的高度為 0 ,節點 2 的高度為 2 ,而節點 4 的高度為 4 。此外,我們定義 *H(T)* 為 *T* 中所有節點的高度總和。給定一個樹狀圖T,請找出 *T* 的根節點以及高度總和 *H(T)* 。 ### 輸入: 第一行有一個正整數 n 代表樹狀圖的節點個數,節點的編號為 1 到 n 。 接下來有 n 行,第 i 行的第一個數字 k 代表節點 i 有 k 個子節點,第 i 行接下來的 k 個數字就是這些子節點的編號。 ### 輸出: 輸出兩行各含一個整數,第一行是根節點的編號,第二行是 *H(T)*。 ## 解題思路 利用 DFS 的技巧,在走訪過程中紀錄 i 節點走過的最大距離,並在迴圈中把所有節點之最大距離加總,同時,也比較所有節點中擁有最大距離的節點,也就是跟節點,最後輸出。 ## 程式碼 ```clike= #include <iostream> #include <vector> using namespace std; #define ll long long vector <ll> tree[100004]; ll h[100004]; ll dfs(ll node){ if(tree[node].size()==0){ h[node]=0; return 0; } if(h[node]!=0){ return h[node]; } ll ch=tree[node].size(); for(ll i=0;i<ch;i++){ h[node]=max(h[node],dfs(tree[node][i])+1); } return h[node]; } int main(){ ll n; while(cin>>n){ fill(h,h+n+1,0); for(ll i=1;i<=n;i++){ tree[i].clear(); ll num; cin>>num; if(num!=0){ for(ll j=1;j<=num;j++){ ll nn; cin>>nn; tree[i].push_back(nn); } } } ll ans=0; ll Node=1; for(ll i=1;i<=n;i++){ ll df=dfs(i); ans+=df; if(df>h[Node]){ Node=i; } } cout<<Node<<endl; cout<<ans<<endl; } } ``` ## 資料來源 [Zerojudge](https://zerojudge.tw/) [題目敘述](https://zerojudge.tw/ShowProblem?problemid=c463) ## 備註 >[name=PeterWang] >[time=Sun, Jun 13, 2021 9:59 AM]