P4017 最大食物链计数(拓扑排序/高中生物)
题意:给你一个食物网,求出食物链条数
题解:
1.设f(i)是以i为终点的食物链条数(这里的食物链不一定是完整的)
2.在建立食物网的过程中,对每个物种,记录捕食它的物种数和它捕食的物种数,记为in(i)和out(i),
3.找到in(i)为0的生物,把它们扔进队列,初始化f[i]=1
4.把队列里第一种生物u拽出来,枚举它所有的捕食者v,那么f[v]=f[v]+f[u]。
5.因为u已经被扔掉了,所以把in(v)减一。如果此时in(v)为0,就把它扔进队列,但此时如果out(v)也为0,说明它是最高营养级,已经到了食物链尽头,所以把ans(答案)加上f[v]即可
6.重复4,5两步,直到队列为空
7.输出答案
时间复杂度为O(n),但不保证此算法在生物考试中的实用性(雾)
题目地址:
https://www.luogu.com.cn/problemnew/show/P4017
1.设f(i)是以i为终点的食物链条数(这里的食物链不一定是完整的)
2.在建立食物网的过程中,对每个物种,记录捕食它的物种数和它捕食的物种数,记为in(i)和out(i),
3.找到in(i)为0的生物,把它们扔进队列,初始化f[i]=1
4.把队列里第一种生物u拽出来,枚举它所有的捕食者v,那么f[v]=f[v]+f[u]。
5.因为u已经被扔掉了,所以把in(v)减一。如果此时in(v)为0,就把它扔进队列,但此时如果out(v)也为0,说明它是最高营养级,已经到了食物链尽头,所以把ans(答案)加上f[v]即可
6.重复4,5两步,直到队列为空
7.输出答案
时间复杂度为O(n),但不保证此算法在生物考试中的实用性(雾)
题目地址:
https://www.luogu.com.cn/problemnew/show/P4017
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define mod 80112002 3 using namespace std; 4 int n,m,u,v,cnt,ans,head[5003],in[5003],out[5003],f[5003]; 5 struct Edge{ 6 int v,next; 7 }e[500005]; 8 queue<int> q; 9 void add(int u,int v){ 10 e[++cnt].v=v; 11 e[cnt].next=head[u]; 12 head[u]=cnt; 13 out[u]++; 14 in[v]++; 15 } 16 int main(){ 17 ios::sync_with_stdio(false); 18 cin>>n>>m; 19 for(int i=1;i<=m;i++){ 20 cin>>u>>v; 21 add(u,v); 22 } 23 for(int i=1;i<=n;i++) 24 if(!in[i]) 25 f[i]=1,q.push(i); 26 while(!q.empty()){ 27 int u=q.front();q.pop(); 28 for(int i=head[u];i;i=e[i].next){ 29 int v=e[i].v; 30 f[v]=(f[v]+f[u])%mod; 31 in[v]--; 32 if(in[v]==0){ 33 if(out[v]==0) 34 ans=(ans+f[v])%mod; 35 else q.push(v); 36 } 37 } 38 } 39 cout<<ans; 40 }