[HAOI2016]食物鏈(拓撲排序 + dp)

鏈接:https://ac.nowcoder.com/acm/problem/20000
來源:牛客網
 

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld

題目描述

如圖所示爲某生態系統的食物網示意圖,據圖回答第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條能量流動關係。 (數據保證輸入數據符號生物學特點,且不會有重複的能量流動關係出現) 

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

輸出

9

隊列記錄當前入度爲0的點,dp[i]表示暫時以 i 點爲結尾的食物鏈的數量,用入度爲0的點更新與它相連的點

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 10;

struct node
{
    int to, next;
}edge[N << 1];

int head[N], in[N], out[N], dp[N], tot, n, m, u, v;

void add(int u, int v)
{
    edge[++tot].next = head[u];
    edge[tot].to = v;
    head[u] = tot;
}

void solve()
{
    queue<int>q;
    for(int i = 1; i <= n; ++i)
    {
        if(in[i] == 0 && out[i] != 0)//食物鏈底端,入度出度都爲0的生物不構成食物鏈
        {
            q.push(i);
            dp[i] = 1;
        }
    }
    while(q.size())
    {
        int u = q.front();
        q.pop();
        for(int i = head[u]; ~i; i = edge[i].next)
        {
            int v = edge[i].to;
            in[v]--;
            dp[v] += dp[u];//更新傳遞
            if(in[v] == 0)
            {
                q.push(v);
            }
        }
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    tot = 0;
    memset(in, 0, sizeof(in));
    memset(out, 0, sizeof(out));
    memset(dp, 0, sizeof(dp));
    memset(head, -1, sizeof(head));
    while(m--)
    {
        scanf("%d%d", &u, &v);
        add(u, v);
        in[v]++;
        out[u]++;
    }
    solve();
    int ans = 0;
    for(int i = 1; i <= n; ++i)
    {
        if(out[i] == 0)//總食物鏈條數即出度爲0的生物佔有的食物鏈的條數之和
            ans += dp[i];
    }
    cout<<ans<<'\n';
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章