【bzoj 4562】食物链(DP+拓扑)HAOI2016

来源:互联网 发布:strider军刀 淘宝 编辑:程序博客网 时间:2024/04/24 15:36

http://www.lydsy.com/JudgeOnline/problem.php?id=4562

题目描述

如图所示为某生态系统的食物网示意图,据图回答第1小题【满满的都是生物的气息emmmmm】
现在给你n个物种和m条能量流动关系,求其中的食物链条数。
物种的名称为从1到n编号
M条能量流动关系形如
a1 b1
a2 b2
a3 b3
……
am-1 bm-1
am bm
其中ai bi表示能量从物种ai流向物种bi,注意单独的一种孤立生物不算一条食物链

输入

第一行两个整数n和m,接下来m行每行两个整数ai bi描述m条能量流动关系。
(数据保证输入数据符号生物学特点,且不会有重复的能量流动关系出现)
1<=N<=100000 0<=m<=200000
题目保证答案不会爆 int

输出

一个整数即食物网中的食物链条数

样例输入

10 16
1 2
1 4
1 10
2 3
2 5
4 3
4 5
4 8
6 5
7 6
7 9
8 5
9 8
10 6
10 7
10 9

样例输出

9

一句话的切题


在一个给定的DAG图中,求任意一条从入度为0的点到出度为0的点的方案数,其中不包括入度和出度都为0的点

思路:

一上来就看成了和上一道并查集的食物链一样的题,恍惚了一下才发现这是个什么东西。餐后小甜点的训练中A题拓扑的题目就是这一道,用裸的迷迷的拓扑排序竟然还过了三个点(姿势好姿势好哈哈哈尬)
事实上没看出来应该用拓扑套上什么,各种跪着哭,最后听他们说是要dp,但是超级没有觉得DP在哪里。。。
首先入度和出度都为0的点要特判,然后设f[i]表示从某个入度为0的点到点i的方案数,然后按照类似拓扑排序的方法,由入度为0的点更新其它点,在此过程中进行累加。

代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<cmath>#define ri register inttypedef long long LL;using namespace std;const int sz = 100010;inline void read(int &x){    x=0;bool f=0;char c=getchar();    while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}    if(f) x*=-1;}inline void we(int x){    if(x<0) putchar('-'),x*=-1;    if(x/10) we(x/10);    putchar(x%10+'0');}int n,m,to[sz<<1],fir[sz],nxt[sz<<1],tot;int cd[sz],rd[sz],ans,f[sz];inline void add(int f,int t){    to[++tot]=t;    nxt[tot]=fir[f];    fir[f]=tot;}queue<int>q;int main(){    int x,y;    read(n),read(m);    for(ri i=1;i<=m;++i)    {        read(x),read(y);        add(x,y);        cd[x]++,rd[y]++;    }    for(ri i=1;i<=n;++i)    {        if(!rd[i])        {            if(cd[i]) f[i]=1;            q.push(i);        }    }    while(!q.empty())    {        x = q.front();//这个x的定义问题有可能会造成3组超时...        q.pop();        for(ri i=fir[x];i;i=nxt[i])        {            f[to[i]]+=f[x],rd[to[i]]--;            if(!rd[to[i]])                q.push(to[i]);        }    }    for(ri i=1;i<=n;++i)        if(!cd[i])            ans+=f[i];    we(ans);    return 0;}