C4-Zexal的食物链

考点

DFS

题目描述

现在给你n个物种和m条能量流动关系,求其中的食物链条数。

物种的名称为从1n的编号。 m条能量流动关系形如b 表示能量从物种a 流向物种b。注意单独的一种孤立生物不算一条食物链。

此处的食物链指的是从生产者到当前链上最高级消费者的一条链。(入度为0出度为0的一条独立路径)

输入

第一行两个整数n和m,接下来 m行每行两个整数a b描述 m条能量流关系。

(保证输入数据符合生物学特点,且不会有重复的能量流动关系出现)

(1<=n<=100000 1<=m<=200000)

输出

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

输入样例

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

思路

For(生物 B in 生物A的后继)
  以生物A开头的食物链数量 += 以生物B开头的食物链数量;

注意:单独的一种孤立生物不算一条食物链。因此我们要保存每个生物的入度和出度,对于出度入度都是0的就不计算
我们对每一个无入度而有出度的生物进行遍历
如果这个生物没有出度,这个食物链就到头了,以它开始的食物链只能有一条
如果我们已经访问过这个生物,就可以直接加上以这个生物开头的食物链数量
如果没有访问过这个生物,那么我们就可以遍历它后继的所有生物

代码

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <vector>
 5 /*C4-Zexal的食物链*/
 6 using namespace std;
 7 vector<int> g[100005];
 8 int n,m;
 9 int in[100005], out[100005], vis[100005];
10 
11 int dfs(int x)
12 {
13     int tot = 0;
14     if(!out[x] && in[x]) return vis[x]=1;//出度为,以其开头只能有1个
15     if(vis[x]) return vis[x];            //判断是否记忆过,减少计算量
16     for(int i=0;i<g[x].size();i++)        
17     {
18         tot += dfs(g[x][i]);            //以生物A开头的食物链数量 += 以生物B开头的食物链数量;
19     }
20     vis[x] = tot;                        //记忆,减少计算量
21     return tot;
22 }
23 int main()
24 {25     int ans = 0;
26    cin>>n>>m;
27     for(int i = 0; i < m; i++)
28     {
29         int a,b;
30        cin>>a>>b;
31         g[a].push_back(b);
32         in[b]++;
33         out[a]++;
34     }
35     for(int i = 0; i < n; i++)            //For(生物 B in 生物A的后继)
36         if(!in[i] && out[i])            //只计算入度为0
37             ans += dfs(i);                //以生物A开头的食物链数量 += 以生物B开头的食物链数量;
38     cout<<ans<<endl;
39     return 0;
40 }

猜你喜欢

转载自www.cnblogs.com/kubab119/p/11822916.html