河南OI2016·食物链

题目描述

如图所示为某生态系统的食物网示意图,据图回答第1小题.
题母意图
1.数一数,在这个食物网中有几条食物链(  )
现在给你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条能量流动关系。
(数据保证输入数据符号生物学特点,且不会有重复的能量流动关系出现)

输出

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

样例输入

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

提示

就是上面题目描述1的那个图
各个物种的编号依次为
草 1兔 2狐 3鼠 4猫头鹰 5吃虫的鸟 6蜘蛛 7蛇 8青蛙 9食草昆虫 10

数据范围

1<=N<=100000 0<=m<=200000
题目保证答案不会爆int

思路

1e5的点2e5的边的有向图,邻接表存储;
从每一个生产者出发,DFS,直到终极消费者,为一条食物链;
记忆化,如果当前点后面有n条路,那么记录下来,以后再到这个点不必向下递归,直接调用;
注意:一个孤立的点并不是一条食物链!(PS:生物老师怎么说的来?食物链必须由生产者指向消费者,那么1条链至少有2个生物~)

Code

#include <bits/stdc++.h>
using namespace std;
const int mx = 200010;
struct node{
    int to,next;
}edge[mx];
int m,n,tot,head[mx],a,b,ans;
int ss[mx];
bool vi[mx];
void add_edge(int u,int v){
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void dfs(int p) {
    if (head[p]==-1) {
        ss[p]=1;
        ans++;
        return;
    }
    if (ss[p]) {
        ans+=ss[p];
        return;
    }
    for (int i=head[p];i!=-1;i=edge[i].next) {
        //cout<<'i'<<i<<endl;
        dfs(edge[i].to);
        ss[p]+=ss[edge[i].to];
    }
}
int main() {
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof(head));
    while (m--)  {
        scanf("%d%d",&a,&b);
        add_edge(a,b);
        vi[b]=true;
    }
    for (int i=1;i<=n;++i)
        if (!vi[i]&&(~head[i])) dfs(i);


    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值