PAT 7-7 小字輩 (25 分)
小白入門不懂BFS(廣度優先搜尋)和DFS(深度優先搜尋),如果不懂請參考原作者這裡
-------------------------------https://blog.csdn.net/raphealguo/article/details/7523411--------------------------------------------------------
本題給定一個龐大家族的家譜,要請你給出最小一輩的名單。
輸入格式:
輸入在第一行給出家族人口總數 N(不超過 100 000 的正整數) —— 簡單起見,我們把家族成員從 1 到 N 編號。隨後第二行給出 N 個編號,其中第 i 個編號對應第 i 位成員的父/母。家譜中輩分最高的老祖宗對應的父/母編號為 -1。一行中的數字間以空格分隔。
輸出格式:
首先輸出最小的輩分(老祖宗的輩分為 1,以下逐級遞增)。然後在第二行按遞增順序輸出輩分最小的成員的編號。編號間以一個空格分隔,行首尾不得有多餘空格。
輸入樣例:
9
2 6 5 5 -1 5 6 4 7
輸出樣例:
4
1 9
最初思路:最開始有思路 如下圖,嘗試用vector寫,但是發現解決不了不斷搜尋的問題,如果非要去暴力搜尋,貌似超級麻煩;
這次收穫挺大,一直不懂bfs和dfs,這次也系統的看了一下,一會兒再去搞兩道練習一下;
最終思路:我的最初思路,和我的畫的圖都是沒問題的!看了一下網上大牛的解題方法,用到了圖的bfs(廣度優先搜尋),然後就學習了一下,還利用了佇列!
步驟:
1,我們把輸入的資料利用vector儲存,如圖,為我們後續步驟做基礎!在輸入期間標記老祖宗的下標(一開始就想到的)
2,我們建立一個數組,這個陣列的用處就是標記每個人的輩分,最終,利用這個輩分找到我們所要的最小輩分(數是最大值),這裡我們先把老祖宗的輩分設為1,即:int vv[100005]; vv[lzz]=1;
3, 我們先把老祖宗的下標入隊,看老祖宗這哥陣列有幾個元素,如圖2,利用向下搜尋。如圖3;並且不斷更新最小輩的值;
#include<iostream> #include<vector> #include<cstdio> #include<set> #include<map> #include<string> #include<string.h> #include<algorithm> #include<cmath> #include<stdlib.h> #include<ctype.h> #include<stack> #include<queue> #include<list> using namespace std; vector<int>v[200005]; int vv[100005]; queue<int>q; int main(){ int n,x,lzz;//lzz 記錄老祖宗 scanf("%d",&n); if(n==1){ } for(int i=1; i<=n; i++){ scanf("%d",&x); if(x==-1) lzz=i; else v[x].push_back(i); } if(n==1){ printf("%d\n%d",1,1); return 0; } q.push(lzz); int bfen=1; //統計輩分 vv[lzz]=1; while(!q.empty()){ int temp = q.front(); q.pop(); for(int i=0;i<v[temp].size();i++){ vv[v[temp][i]] = vv[temp]+1;//更新每個人的輩分 bfen = max(bfen,vv[v[temp][i]]);//更新(獲得)最小輩分的值 q.push(v[temp][i]);//把下一次要遍歷的入隊 } } printf("%d\n",bfen); int flag = 0; for(int i=1;i<=n;i++){ if(vv[i]==bfen){ if(!flag){ printf("%d",i); flag = 1; } else printf(" %d",i); } } }