題目
給你一個食物網,你要求出這個食物網中最大食物鏈的數量。
(這裏的“最大食物鏈”,指的是生物學意義上的食物鏈,即最左端是不會捕食其他生物的生產者,最右端是不會被其他生物捕食的消費者。)
由於這個結果可能過大,你只需要輸出總數模上 80112002的結果。
輸入格式
第一行,兩個正整數n、m,表示生物種類 n 和喫與被喫的關係數 m。
接下來 m 行,每行兩個正整數,表示被喫的生物A和喫A的生物B。
輸出格式
一行一個整數,爲最大食物鏈數量模上 80112002的結果。
輸入輸出樣例
輸入
5 7
1 2
1 3
2 3
3 5
2 5
4 5
3 4
輸出
5
說明/提示
各測試點滿足以下約定:
樣例中食物鏈關係圖
動態規劃——物種關係
-
最大食物鏈計數 = 以 1 爲起點的食物鏈數量
-
①、以 1 爲起點的食物鏈數量 = 以 2 爲起點的食物鏈數量 + 以 3 爲起點的食物鏈數量
最大食物鏈計數 = 以 2 爲起點的食物鏈數量 + 以 3 爲起點的食物鏈數量 -
①、以 2 爲起點的食物鏈數量 = 以 3 爲起點的食物鏈數量 + 以 5 爲起點的食物鏈數量
②、以 3 爲起點的食物鏈數量 = 以 5 爲起點的食物鏈數量 + 以 4 爲起點的食物鏈數量
最大食物鏈計數 = 3 * 以 5 爲起點的食物鏈數量 + 以 3 爲起點的食物鏈數量 + 2 * 以 4 爲起點的食物鏈數量 -
①、以 4 爲起點的食物鏈數量 = 以 5 爲起點的食物鏈數量
②、以 5 爲起點的食物鏈數量 = 1
最大食物鏈計數 = 5 * 以 5 爲起點的食物鏈數量 = 5
上面是正推的過程
爲了方便理解,代碼中通過逆推的方式實現
①、記錄每個物種能喫多少物種。(eat)
②、記錄每個物種能被多少種物種喫。(beat)
③、記錄每個物種能食用那些物種。(vector)
//逆推
#include<bits/stdc++.h>
using namespace std;
int eat[5010], beat[5010];
vector <int> gx[5010];
int total[5010], ans=0;
int main(){
memset(eat, 0, sizeof(eat));
memset(beat, 0, sizeof(beat));
memset(total, 0, sizeof(total));
int n, m;
cin>>n>>m;
for(int i=0; i<m; i++){
int a, b;
cin>>a>>b;
beat[a]++; // 可喫 a 物種的數量
eat[b]++; // b 物種可喫的數量
gx[b].push_back(a); // b 可喫 a
}
queue <int> q;
//初始化
for(int i=1; i<=n; i++){
if(beat[i]==0){
total[i]=1; //每個“終點”賦值爲1
q.push(i); //並插入隊列中
}
}
while(!q.empty()){
int top = q.front();
q.pop();
for(int i=0; i<gx[top].size(); i++){
int k = gx[top][i];
//推出以 k 爲起點的食物鏈數
total[k] = (total[k]+total[top])%80112002;
//減去物種 k 可被其他物種喫的數量
beat[k]--;
//當beat[k]==0
//total[k]爲以 k 爲起點的最大食物鏈數
if(beat[k]==0){
//回到起點
if(eat[k]==0){
ans = (ans + total[k])%80112002;
}
//未到起點
else{
q.push(k);
}
}
}
}
cout<<ans;
return 0;
}
如果文章對你有幫助,請給個贊吧~