[BZOJ2815][ZJOI2012]災難(拓撲+倍增)

【問題描述】

阿米巴是小強的好朋友。

阿米巴和小強在草原上捉螞蚱。小強突然想,如果螞蚱被他們捉滅絕了,那麼吃螞蚱的小鳥就會餓死,而捕食小鳥的猛禽也會跟着滅絕,從而引發一系列的生態災難。

學過生物的阿米巴告訴小強,草原是一個極其穩定的生態系統。如果螞蚱滅絕了,小鳥照樣可以吃別的蟲子,所以一個物種的滅絕並不一定會引發重大的災難。

我們現在從專業一點的角度來看這個問題。我們用一種叫做食物網的有向圖來描述生物之間的關係:

一個食物網有 N個點,代表 N 種生物,如果生物 x 可以吃生物 y,那麼從 y向 x 連一個有向邊。 這個圖沒有環。

圖中有一些點沒有連出邊,這些點代表的生物都是生產者,可以通過光合作用來生存; 而有連出邊的點代表的都是消費者,它們必須通過吃其他生物來生存。

如果某個消費者的所有食物都滅絕了,它會跟着滅絕。

我們定義一個生物在食物網中的“災難值”爲,如果它突然滅絕,那麼會跟着一起滅絕的生物的種數。

舉個例子:在一個草場上,生物之間的關係是:

如果小強和阿米巴把草原上所有的羊都給嚇死了,那麼狼會因爲沒有食物而滅絕,而小強和阿米巴可以通過吃牛、牛可以通過吃草來生存下去。所以,羊的災難值是 1。但是,如果草突然滅絕,那麼整個草原上的 5 種生物都無法倖免,所以,草的災難值是 4。

給定一個食物網,你要求出每個生物的災難值。

【輸入格式】
輸入文件 catas.in 的第一行是一個正整數 N,表示生物的種數。生物從 1 標號到 N。

接下來 N 行,每行描述了一個生物可以吃的其他生物的列表,格式爲用空格隔開的若干個數字,每個數字表示一種生物的標號,最後一個數字是 0 表示列表的結束。

【輸出格式】
輸出文件 catas.out 包含N行,每行一個整數,表示每個生物的災難值。

【樣例輸入】
5
0
1 0
1 0
2 3 0
2 0

【樣例輸出】
4
1
0
0
0

【樣例說明】
樣例輸入描述了題目描述中舉的例子。

【數據規模】
對 50%的數據,N ≤ 10000。
對 100%的數據,1 ≤ N ≤ 65534。
輸入文件的大小不超過 1M。保證輸入的食物網沒有環。


算法討論

拓撲排序(50%):
    枚舉所有N種生物並進行拓撲排序,同時計算每個生物的災難值。
    時間複雜度O(N^2)  

拓撲+倍增(100%):
    我們需要構造一棵“滅絕樹”。
    “滅絕樹”滿足以下性質:對於一棵多叉樹的任意一個結點,當它“滅絕”時,它所有的後代也會跟着“滅絕”。
    再回過來看這道題,題目要求的是某種生物“滅絕”後跟着“滅絕”的其他生物的數量,即這種生物在“滅絕樹”中的後代數量。
    那麼問題來了,怎麼建立“滅絕樹”?
    很顯然,一種生物會“滅絕”只有兩種情況:一是它原本就“滅絕”(即我們要求災難值的那種生物),二是它所有的食物都“滅絕”。
    第一種情況不用考慮,那麼我們來考慮第二種情況。
    假設有生物I。很顯然,只有當生物I的所有食物的最近公共祖先(LCA)J“滅絕”時,生物I的所有食物纔會同時“滅絕”(顯然這裏就要用到倍增求LCA的算法),然後,我們將生物I作爲生物J的一個新的孩子節點,表示當J“滅絕”時,I也會跟着“滅絕”(因爲它所有的食物都“滅絕”了)。
    根據題目需求,最後只要輸出每種生物在“滅絕樹”中的所有後代數量(數量的計算可以在每次“滅絕樹”加入新節點時進行一次DFS)就可以了。
發佈了33 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章