[HAOI2016]食物链

[HAOI2016]食物链

题目描述

 

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

输入输出格式

输入格式:

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

输出格式:

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

输入样例#1 

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

输出样例#1 

9

讲解:

这道题十分的水,是一道拓扑排序的模板题,只需注意单独的一种孤立生物不算一条食物链,之后就是一个dp。

代码实现:

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
using namespace std;
const int N=100010,M=200010;
struct node
{
    int to,next;
}edge[M];
int head[N],cnt=-1,n,m;
void add(int x,int y)
{
    edge[++cnt].to=y;
    edge[cnt].next=head[x];
    head[x]=cnt;
}                                     //建边 
int ind[N],dp[N],book[N],ans;
int main()
{
    memset(head,-1,sizeof(head));
    int i,j,x,y;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);                     //有向边 
        ind[y]++;                     //每一个入度 
    }
    queue<int> q;
    for(i=1;i<=n;i++)
    {
        if(ind[i]==0)
        {
            q.push(i);
            dp[i]=1;
            book[i]=1;
        }
    }                                //寻找拓扑图(DAG)的起点 
    while(!q.empty())
    {
        int x=q.front(),i,flag=0;
        q.pop();
        for(i=head[x];i!=-1;i=edge[i].next)
        {
            flag=1;
            ind[edge[i].to]--;
            dp[edge[i].to]+=dp[x];
            if(ind[edge[i].to]==0) q.push(edge[i].to);
        }                           //遍利当前节点的所有出边,并进行dp(累加) 
        if(flag==0 && book[x]==0) ans+=dp[x]; 
                                    //只有当前节点没有出边(就是图的终点)
                                    //并且也不是孤立的生物时才是答案 
    }
    cout<<ans<<endl;
    return 0;
}
View Code
posted @ 2018-09-24 21:28  欢语_暗影  阅读(499)  评论(1编辑  收藏  举报