1. 程式人生 > 實用技巧 >P4017 最大食物鏈計數

P4017 最大食物鏈計數

題目背景

你知道食物鏈嗎?Delia 生物考試的時候,數食物鏈條數的題目全都錯了,因為她總是重複數了幾條或漏掉了幾條。於是她來就來求助你,然而你也不會啊!寫一個程式來幫幫她吧。

題目描述

給你一個食物網,你要求出這個食物網中最大食物鏈的數量。

(這裡的“最大食物鏈”,指的是生物學意義上的食物鏈,即最左端是不會捕食其他生物的生產者,最右端是不會被其他生物捕食的消費者。)

Delia 非常急,所以你只有1秒的時間。

由於這個結果可能過大,你只需要輸出總數模上80112002的結果。

輸入格式

第一行,兩個正整數n、m,表示生物種類n和吃與被吃的關係數m

接下來m行,每行兩個正整數,表示被吃的生物A和吃A的生物B。

輸出格式

一行一個整數,為最大食物鏈數量模上80112002的結果。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

最開始看見這道題目的時候,首先想到的是用DFS或BFS試一試,如果用DFS,顯然超時妥妥的,BFS的話,由層層遞推的關係我們可知,若以某個結點為重點,則最終到該點的食物鏈總條數num為其所有前驅結點總條數num之和,

然而,BFS顯然不行,因為對於某個結點來說,其在食物鏈中可能佔有多個不同級數,只有當這些不同在不同級數上求得的num結果全部得到後,才能將最終結果納入其後驅結點的num中,這個思路已經很明確了,拓撲排序

具體程式碼如下:

#include<iostream>
#include<queue>
#include<vector>
using
namespace std; int main(){ int n,m; //n種動物,m條邊 cin >> n >> m; vector<int> a[n+1]; int book[n+1] = {0}; //記錄入度 int num[n+1] = {0}; queue<int>q; for(int i = 0;i < m;i++){ int x,y; cin >> x >> y; a[x].push_back(y); book[y]++; } for(int i = 1;i <= n;i++){ if(book[i] == 0){ q.push(i); num[i] = 1; // 每個生產者代表一條新路徑開始 } } int aim = 0;//記錄最終結果 while(!q.empty()){ int x = q.front() ; q.pop() ; if(a[x].size() == 0){ aim += num[x]; if(aim >= 80112002) aim %= 80112002; } else for(int i = 0;i < a[x].size() ;i++){ num[a[x][i]] += num[x]; if( num[a[x][i]] >= 80112002) num[a[x][i]] %= 80112002; //注意num的結果可能會超限制int的限制! book[a[x][i]]--; if(book[a[x][i]] == 0) q.push(a[x][i]); } } cout << aim; return 0; }