题目
正文
- 首先,根据题目中的最左端是不会捕食其他生物的生产者,最右端是不会被其他生物捕食的消费者来讲,这个通俗的来理解就是最左端是入度为(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;
}