切換
舊版
前往
大廳
主題

ZeroJudge - c685: 藍燄與社會 解題心得

Not In My Back Yard | 2018-12-23 23:27:04 | 巴幣 0 | 人氣 181

題目連結:


題目大意:
(由於是本人的題目,所以就直接把題目敘述抓過來XD)
每一筆測資的開頭第一列,會給定兩個非負整數 M、N(0 ≦ M ≦ N ≦ 10, 000),表示詢問了 N 個人,但是只有 M 個人回答你。
 
接下來有 M 列,每一列的第一個數字表示被詢問的人之編號(1 ~ N)。接下來有不定量的數字(不會超過 150 個數字),代表這 N 個人之中他所知道的人之編號。
 
上面 M 列結束之後,還會有一列代表你知道 N 個人中的哪些人。
 
註:當編號A認識編號B,則編號B也一定會認識編號A。儘管測資並沒有體現此點。

對於每一筆測資,給出最多會有幾個「團體」存在。
 
註:「團體」即為成員們互相知曉,就算不認識也能透過關係網知道對方(自己也有可能是團體的一員喔)。



範例輸入:
10 5
1 2 3 7
2 1
3 4
4 3 1
5 2 9
3 1 2 3
10 5
1 2 3 7
2 1
3 4
4 3 1
5 2 9
4 1 6 8 10



範例輸出:
4
1



解題思維:
除了前面的小說很長(X)很占版面(O)會逼退不少人以外,這題其實不難。不如說這題拿來練習「深度優先搜尋」(DFS)相當適合,尤其對於程式新手來說(不過用來練習「廣度優先搜尋」(BFS)也可以)。

首先,題目有提到,每一列代表一個回答你的人。會有回答的人編號,然後接著不定量的數字。對於長度不固定,但是保證都在同一列的輸入,C 的話可以使用 scanf("%[^\n]", …… 、C++ 可以使用 getline(cin, ……辦法很多,大部分語言都有讀一整列輸入的函式。

有了以上結果後,再來是儲存的問題。C++ 的話,可以直接使用 vector 。宣告 N × 2 個 vector 來儲存知道的人,同時也要儲存被哪些人知道(編號反過來放而已)。

然後,有個「自己」的存在,也會知道這 N 個人中的某些人。這個「自己」其實就仿照上面那 N 個人的作法,存在同一個陣列就可以了。(本人用來混淆視聽用的XD)

接著就是找「團體」了,假設「自己」的編號是 0 ,那麼我們就從編號 0 開始找找看他認識哪些人。以範例輸入的第一筆為例,測資代表了:
0 (自己)認識 1、2、3
1 認識 2、3、7
2 認識 1
3 認識 4
4 認識 3、1
5 認識 2、9

所以我們的 DFS 函式,會從編號 0 開始跑。因為知道 1 ,所以就跑過去看 1 ;而因為 1 知道 2 ,走去 2 ;因為 1 已經走過了,而 2 又被 5 認識,所以跑去 5 (題目有講,「認識」是雙向的);跑去 9 ,沒有新的人了,所以回到5;也沒有新的人,回到 2 ……以此類推。

所以拜訪的順序大致為下(要看儲存、存取數據的方法):
0 → 1 → 2 → 5 → 9 → 3 → 4 → 7
以上是我們找到的第一個「團體」,然而我們還有 6、8、10 這三個人還沒拜訪過。套用以上方法可以發現他們各自成一個「團體」。因此總共有 4 個「團體」,所以輸出「4」。

而如果是 BFS 會比較像是
0 → 1、2、3 → 7、5、4 → 9
也可以完成任務。

此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。

創作回應

更多創作