题目链接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 }