4562: [Haoi2016]食物链
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 352 Solved: 263
[ Submit][ Status][ Discuss]
Description
如图所示为某生态系统的食物网示意图,据图回答第1小题
现在给你n个物种和m条能量流动关系,求其中的食物链条数。
物种的名称为从1到n编号
M条能量流动关系形如
a1 b1
a2 b2
a3 b3
......
am-1 bm-1
am bm
其中ai bi表示能量从物种ai流向物种bi,注意单独的一种孤立生物不算一条食物链
Input
第一行两个整数n和m,接下来m行每行两个整数ai bi描述m条能量流动关系。
(数据保证输入数据符号生物学特点,且不会有重复的能量流动关系出现)
1<=N<=100000 0<=m<=200000
题目保证答案不会爆 int
Output
一个整数即食物网中的食物链条数
Sample Input
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 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
Sample Output
9
思路:
1、一开始在网上还找到了一个公式:食物链条数=分叉边数-分叉点数+1....
尼玛大骗纸不好用啊、分叉到两个子树中就尼玛不是一个东西了好伐。
2、统计计数问题考虑dp,设定dp【i】表示以i为根的子树食物链的条数。
那这个题就是水题啊,dp【i】=Σdp【v】;
然后设定个超级源点连度为0的所有节点,那么dp【0】就是答案啊。
3、注意孤立节点不算答案啊。就没了啊。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
vector<int >mp[100600];
int degree[100600];
int dp[100600];
int n,m;
int Dfs_Dp(int u)
{
if(dp[u]==-1)
{
dp[u]=0;
int size=mp[u].size();
for(int i=0;i<size;i++)
{
int v=mp[u][i];
dp[u]+=Dfs_Dp(v);
}
if(size==0)dp[u]=1;
return dp[u];
}
else return dp[u];
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(dp,-1,sizeof(dp));
memset(degree,0,sizeof(degree));
for(int i=0;i<=n;i++)mp[i].clear();
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
mp[x].push_back(y);
degree[y]++;
}
for(int i=1;i<=n;i++)
{
if(degree[i]==0&&mp[i].size()>0)mp[0].push_back(i);
}
if(mp[0].size()>0)
Dfs_Dp(0);
if(dp[0]<0)dp[0]=0;
printf("%d\n",dp[0]);
}
}