首页 > 其他分享 >[刷题笔记] Luogu P4017 最大食物链计数

[刷题笔记] Luogu P4017 最大食物链计数

时间:2023-07-12 17:11:37浏览次数:50  
标签:食物链 int Luogu 出度 dfs 拓扑 include P4017 刷题

Problem

Description

首先明确,最大食物链指生产者到顶级消费者(即最高营养级),而不是最长的食物链

这样,我们就可以将题意转化为:

在一张图中,求入度为0的点到出度为0的点路径数量

这不妥妥的拓扑排序嘛(这题竟然在dp训练题单里,想了好久的dp)

Solution

虽说是拓扑排序,但并不完全是。

我们先回忆一下拓扑排序是如何进行的:

  • 找到一个入度为0的点
  • 删除与这个点连接的点
  • 继续找入度为0的点

对于这道题,我们显然不能删边,直接dfs搜索即可。

但是直接dfs复杂度太高,需要记忆化一下,记录每个点作为底的路径个数,若搜索到出度为0的点则返回1(代表一个路径)

显然我们只需要对刚开始入度为0的点dfs(拓扑排序,因为生产者的入度为0),题意明确了就比较明了。

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#define N 5000000
#define mod 80112002
using namespace std;
int in[N],out[N];
vector <int> Edge[N];
int n,m;
int rem[N];
int ans = 0;
int dfs(int x)
{
    if(rem[x]) return rem[x]; //记忆化
    if(!out[x]) return 1; //如果出度为0则代表一条路径
    int sum = 0;
    for(int i=0;i<Edge[x].size();i++)
    {
        sum += dfs(Edge[x][i]); //记录当前节点为底的路径数量
        sum %= mod; //能%就%一下吧,防止炸
    }
    rem[x] = sum%mod;//同上
    return sum;//返回该点为底路径的数量即可
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        Edge[x].push_back(y);
        out[x] ++; //记录入度出度
        in[y] ++;
    }
    for(int i=1;i<=n;i++)
    {
        if(!in[i])  //只需要对入度为0的点拓扑排序即可
        {
            ans +=dfs(i);
            ans %= mod;
        }
    }
    cout<<ans%mod<<endl;
    return 0;
}

标签:食物链,int,Luogu,出度,dfs,拓扑,include,P4017,刷题
From: https://www.cnblogs.com/SXqwq/p/17548242.html

相关文章

  • [刷题笔记] Luogu P3183 食物链
    ProblemDescription通俗一点就是在一张图上求入度为0的点到出度为0的点路径的个数。Solution简要题意后发现可以拓扑排序?这里主要介绍记忆化搜索。记忆化搜索是指记住当前节点的状态,待下次搜到这里直接调用即可,无需继续搜索。显然由记忆化搜索延伸到dp,但如果状态设计很复杂......
  • RSA刷题系列
    1,共享素数1)[闽盾杯2021]decode题目:n1:15228664629164509105936278301396170708905691970126305196584505186788860519598413718493859625462561931380632032431490419378905593909771649295663481782473029836321132574188559245931660756414915507930357509270674460219615......
  • 概率/期望dp刷题整理
    Bagofmice题意:有w只白鼠和b只黑鼠,公主和龙轮流抓老鼠,其中龙每抓一只老鼠就会有一只未被抓住的老鼠逃走,先抓到一只白鼠的获胜,问公主获胜的概率是多少Solution令dp[i][j]表示还剩i只白鼠和j只黑鼠时公主获胜的概率如果公主直接抓住一只白鼠,获胜的概率是\[\frac{i}{i+j}\]如......
  • ctfshow刷题(Java反序列化)
    CTFshowJava反序列化web846urldns链importjava.io.ByteArrayOutputStream;importjava.io.IOException;importjava.io.ObjectOutput;importjava.io.ObjectOutputStream;importjava.lang.reflect.Field;importjava.net.URL;importjava.util.Base64;i......
  • 【笔试实战】LeetCode题单刷题-编程基础 0 到 1【三】
    682. 棒球比赛题目链接682. 棒球比赛题目描述你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成,过去几回合的得分可能会影响以后几回合的得分。比赛开始时,记录是空白的。你会得到一个记录操作的字符串列表 ops,其中 ops[i] 是你需要记录的第 i 项操作......
  • 【笔试实战】LeetCode题单刷题-编程基础 0 到 1【二】
    1822. 数组元素积的符号题目链接1822. 数组元素积的符号题目描述已知函数 signFunc(x) 将会根据 x 的正负返回特定值:如果 x 是正数,返回 1 。如果 x 是负数,返回 -1 。如果 x 是等于 0 ,返回 0 。给你一个整数数组 nums 。令 product 为数组 nums......
  • 【笔试实战】LeetCode题单刷题-编程基础 0 到 1【一】
    1768. 交替合并字符串题目链接1768. 交替合并字符串题目描述给你两个字符串 word1 和 word2 。请你从 word1 开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。返回 合并后的字符串 。示例1:输入:wor......
  • pwn | buuctf刷题(一)
    test_your_ncnc连上去就是一个shellpwn1gets栈溢出,ret2text打远程的时候遇到如下报错,原因可能有两个timeout:themonitoredcommanddumpedcore一是get_flag后未正常退出,需要给get_flag的返回地址写个exit二是栈未对齐,导致程序异常退出,如下所示,ret时rsp为...968成功进......
  • 【置顶】luogu题解集(2023-07-01更新)
    P8679[蓝桥杯2019省B]填空问题题解题目传送门欢迎大家指出错误并联系这个蒟蒻更新日志2023-05-2521:02文章完成2023-05-2711:34文章通过审核2023-06-2021:03优化了文章代码格式试题A:组队【解析】本题是一道经典的DFS搜索题,每次对各号位的选手进行DFS,......
  • [刷题记录Day1]Leetcode列表专题
    No.1题目二分查找思路要素:原数组升序排列清楚地定义左右边界优化空间:数组有序,通过第0元素和最后元素,可以避免查找不在数组范围内的target代码publicstaticintsearch(int[]nums,inttarget){//避免target小于nums[0],大于nums[nums.length-1]时参与运算......