【luogu P4017 最大食物链计数】 题解

题目链接:https://www.luogu.org/problemnew/show/P4017

DAG + DP

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 500010;
const int mod = 80112002;
struct edge{
    long long from, to, next;
}e[maxn<<2];
long long head[maxn], cnt;
long long n, m, indrg[maxn], outdrg[maxn], f[maxn], str[maxn], strnum, end[maxn], endnum, ans;
long long H, T, Q[maxn];
void add(long long u, long long v)
{
    e[++cnt].from = u;
    e[cnt].next = head[u];
    e[cnt].to = v;
    head[u] = cnt;
}
int main()
{
    memset(head, -1, sizeof(head));
    scanf("%lld%lld",&n,&m);
    for(long long i = 1; i <= m; i++)
    {
        long long u, v;
        scanf("%lld%lld",&u,&v);
        add(u, v);
        indrg[v]++; outdrg[u]++;
    }
    T = 0, H = 1;
    for(long long i = 1; i <= n; i++)
    {
        if(indrg[i] == 0)
        Q[++T] = i, str[++strnum] = i;
        if(outdrg[i] == 0)
        end[++endnum] = i;
    }

    while(H <= T)
    {
        long long u = Q[H++];
        for(long long i = head[u]; i != -1; i = e[i].next)
        {
            long long v = e[i].to;
            indrg[v]--;
            if(indrg[v] == 0)
            Q[++T] = v;
        }
    }

    for(int i = 1; i <= strnum; i++)
    f[str[i]] = 1;

    for(long long i = 1; i <= n; i++)
    {
        long long u = Q[i];
        for(long long j = head[u]; j != -1; j = e[j].next)
        {
            long long v = e[j].to;
            f[v] += f[u] % mod;
        }
    }

    for(int i = 1; i <= endnum; i++)
    ans += f[end[i]] % mod;

    printf("%lld",ans % mod);
    return 0;
}

原文地址:https://www.cnblogs.com/MisakaAzusa/p/9648933.html

时间: 2024-11-05 20:40:57

【luogu P4017 最大食物链计数】 题解的相关文章

最大食物链计数 题解

文字讲解 题目分析: 首先 ,要知道这道拓扑排序题目的性质. 食物链中的生物 -- 节点 生物之间的关系 -- 有向边 为了方便描述,我们 将 最左端是不会捕食其他生物的生产者 叫做 最佳生产者 将 最右端是不会被其他生物捕食的消费者 叫做 最佳消费者 数据中不会出现环 那么,"最大食物链"就是左端是 最佳生产者 ,右端是 最佳消费者 思路引导 易得,想要找到一条 最大食物链 ,则起始点入度要为0,终点出度要为0.于是有: 既要记录入度,还要记录出度! 现在的问题就是,如何找到所有的最

luogu P3183 [HAOI2016]食物链

二次联通门 : luogu P3183 [HAOI2016]食物链 /* luogu P3183 [HAOI2016]食物链 记忆化搜索 */ #include <cstdio> #include <iostream> const int BUF = 12312312; char Buf[BUF], *buf = Buf; inline void read (int &now) { for (now = 0; !isdigit (*buf); ++ buf); for (;

luogu_4017【题解】最大食物链计数(拓扑排序)

题目:https://www.luogu.org/problemnew/show/P4017 由于这个题有严格的偏序关系(应该严格吧).明显就可以想到拓扑排序. 用吃与被吃建图.同时记录出度与入度. 求拓扑排序的同时.如果谁的出度为 0 .则证明这条链到头.ans++. 最后输出答案. 代码如下: 这是邻接表存图的,速度比较快. #include<bits/stdc++.h> #define sc(x) scanf("%d",&x) using namespace

【luogu P1144 最短路计数】 题解

题目链接:https://www.luogu.org/problemnew/show/P1144 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <queue> 5 #include <vector> 6 using namespace std; 7 const int mod = 100003; 8 const int maxn = 2000

P1144 最短路计数 题解 最短路应用题

题目链接:https://www.luogu.org/problem/P1144 其实这道题目是最短路的变形题,因为数据范围 \(N \le 10^6, M \le 2 \times 10^6\) ,所以直接用Dijkstra算法是不行的,可以使用 Dijkstra+堆优化 或者 SPFA算法来实现. 我这里使用 SPFA算法 来实现 (不会Dijkstra堆优化囧) 这道题目因为需要计数,所以需要在dist数组基础上再开一个cnt数组,其含义如下: \(dist[u]\) :起点 \(1\)

【luogu P1455 搭配购买】 题解

题目链接:https://www.luogu.org/problemnew/show/P1455 一句话题目做法:并查集合并+01背包 启示:要每次再find一遍.路径压缩会快.因为合并的时候如果是1连3,3连2,4连2,最后也不能保证一步就能连到fa上去. 结果会是fa[2] = fa[3] = fa[4] = 2. fa[1] = 3. 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm>

【luogu P2455 [SDOI2006]线性方程组】 题解

题目链接:https://www.luogu.org/problemnew/show/P2455 嗯...在消元过程中不要直接拿矩阵元素自己消,会把自己消成0. 1 #include <algorithm> 2 #include <cstdio> 3 #include <cmath> 4 #include <iostream> 5 using namespace std; 6 const int maxn = 200; 7 const double eps

SDOI2016排列计数 题解

最近学插头DP学得有点不舒服,然后学什么斯坦纳树也学不动,于是就来写写题解,正好有助于巩固一下所学内容 题意较为简单,就是要求对于一个\(1-n\)的序列的全排列中,正好有\(m\)个位置满足\(a[i]==i\)(称其为"稳定的")的排列个数. 很明显,我们可以先固定\(m\)个位置,使得这些位置都为"稳定的",那么还剩下\(n-m\)个位置.因为只能恰好有\(m\)个稳定的数,所以这\(n-m\)个数必须都不是稳定的.也就是说,这\(n-m\)个数必须都不在它们

luogu P2992 [USACO10OPEN]三角形计数Triangle Counting

https://www.luogu.org/problemnew/solution/P2992 考虑包含原点,不包含原点的三角形有什么特征. 包含原点的三角形:任意找一个顶点和原点连线,一定能把另外两个顶点隔开到两侧. 不包含原点的:三个顶点中只有一个顶点满足:和原点连线后,能把另外两个顶点隔开到两侧. 因此我们统计这样的三点组(x,y,z)的数目:x和原点的连线能把y和z隔开在两侧. 一共C(n,3)个三角形,包含原点的贡献3个三点组,不包含的只贡献1个. 统计三点组的数目只需要把所有点按照极