P4017 最大食物链计数

题目链接https://www.luogu.com.cn/problem/P4017

知识点:拓扑排序+动态规划

一、刚开始审题不清,误认为是求AOV最长生物链上生物的个数,便出现如下代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int p=80112002;
 4 int n, m, ans;
 5 vector<int>g[5005];
 6 int dp[5005], ind[5005];
 7 queue<int>que;
 8 int main()
 9 {
10     scanf("%d%d", &n, &m);
11     for(int i=1; i<=m; i++){
12         int a, b;
13         scanf("%d%d", &a, &b);
14         g[b].push_back(a);
15         ind[a]++;
16     }
17     for(int i=1; i<=n; i++)
18         if(!ind[i]){
19             dp[i]=1;
20             que.push(i);
21         }
22     while(!que.empty()){
23         int f=que.front();
24         for(int i=0; i<g[f].size(); i++){
25             int t=g[f][i];
26             dp[t]=max(dp[t], dp[f]+1);
27             ind[t]--;
28             if(!ind[t])
29                 que.push(t);
30         }
31         que.pop();
32     }
33     for(int i=1; i<=n; i++)ans=max(ans, dp[i]);
34     printf("%d", ans%p);
35     
36     return 0;
37 }

结果爆0

重新审题后发现一下关键信息:(这里的“最大食物链”,指的是生物学意义上的食物链,即最左端是不会捕食其他生物的生产者,最右端是不会被其他生物捕食的消费者。)重要信息

经过样例多次尝试分析得知要求:DAG中路径数(起始点为入度为0的生物,终点为出度为0的路径数)

根据题意分析:设dp[i]为起始点(入度为0的点)到达顶点i的路径数,初始值入度为0的点dp[]为1

          拓扑排序过程中状态转移方程为dp[i]=sum(dp[可吃i])

       答案为 sum(dp[出度为0])

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int p=80112002;
 4 int n, m, ans;
 5 vector<int>g[5005];
 6 int dp[5005], ind[5005], outd[5005];//dp[i]表示从起始点到i的路径数 in[i]统计入度 out[i]统计出度 
 7 queue<int>que;
 8 int main()
 9 {
10     scanf("%d%d", &n, &m);
11     for(int i=1; i<=m; i++){
12         int a, b;
13         scanf("%d%d", &a, &b);
14         g[b].push_back(a);//统计b能吃的生物 
15         ind[a]++;//统计a的入度 :即a作为被吃生物的对数 
16     }
17     for(int i=1; i<=n; i++){
18         if(!ind[i]){//入度为0的生物dp初始化为1,加入队列 
19             dp[i]=1;
20             que.push(i);
21         }
22         if(!g[i].size())
23             outd[i]=1;//统计出度为0的生物,答案要求所有出度为0生物dp之和 ,可在样例中添加节点分析 
24     }
25         
26     while(!que.empty()){
27         int f=que.front();
28         for(int i=0; i<g[f].size(); i++){//查找跟f相连接的点,即能被f吃掉的生物 
29             int t=g[f][i];
30             dp[t]=(dp[t]%p+dp[f]%p)%p;//状态转移方程,画图分析可得 
31             ind[t]--;//入度减一 
32             if(!ind[t])//如果度为0则进入下一阶段 
33                 que.push(t);
34         }
35         que.pop();
36     }
37     for(int i=1; i<=n; i++)
38         if(outd[i])//统计出度为0,即生物链终点的dp之和 
39             ans=(ans%p+dp[i]%p)%p;
40     
41     printf("%d", ans%p);
42     
43     return 0;
44 }
原文地址:https://www.cnblogs.com/tflsnoi/p/14764912.html