P4017 最大食物链计数

题目

P4017.png

正文

  • 首先,根据题目中的最左端是不会捕食其他生物的生产者,最右端是不会被其他生物捕食的消费者来讲,这个通俗的来理解就是最左端是入度为(0)的点,最右端是出度为(0)的点而且并不是(DAG)上最长的链,只要满足左右都不能再走的条件就好了
  • 那么我们只要求出以(i)为结尾的链的个数(我们明显可以知道链的根是入度为(0)的点)记为(f[i]),显然,算法是topo这个有趣的东西啦。
  • 最后找出所有出度为(0)的点(i),并把(f[i])累加。

Code

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
using namespace std;
#define reint register int
#define ull unsigned ll
#define INF 0x3f3f3f3f
#define ll long long
#define GC getchar()
#define MOD 80112002
#define MAXM 500005
#define MAXN 5005
#define R read()
ll read(){
    char c=GC; ll s=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-f;c=GC;}
    while(c>='0'&&c<='9'){s=s*10+c-'0';c=GC;}
    return s*f;
}
int head[MAXN],tot;
struct node{
    int to,nxt;
}e[MAXM];
void add(int x,int y) { e[++tot].nxt=head[x]; e[tot].to=y; head[x]=tot; }
//正常的存图建图
int n,m,ans,in[MAXN],out[MAXN],f[MAXN];
queue<int> q;
//亿些正经的变量
int main(){
    n=R; m=R;
    for(int i=1;i<=m;++i) { int u=R,v=R; add(v,u); ++in[u]; ++out[v]; }
    //输入&建图
    for(int i=1;i<=n;++i) if(!in[i]) q.push(i),f[i]=1;
    //找出入度为0的点, 也就是链的根
    while(!q.empty()){
        int u=q.front(); q.pop();
        //拿出来利用->丢弃
        for(int i=head[u];i;i=e[i].nxt){
            //找出u点的所有孩子
            int v=e[i].to; (f[v]+=f[u])%=MOD; --in[v];
            //更新f[v]
            if(!in[v]){
                //如果更新完毕
                q.push(v);
                //可利用->入队
                if(!out[v]) (ans+=f[v])%=MOD;
                //如果是链的底, 累加
            }
        }
    }
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/FUXyao/p/13993734.html