Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 744 Solved: 458
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
Sample Output
9
HINT
Source
显然23333,这题直接跑一边拓扑序就可以了,然后每次去更新子点,初始化入度为0的点的dp值为1,然后往下递推即可,最后计算的是出度为0并且原来的入度不为0的点的dp值的和233
#include<bits/stdc++.h>
using namespace std;
queue<int>q;
const int MAXN = 100000 + 10;
int head[MAXN], dp[MAXN], tail, n, m, in[MAXN], out[MAXN];
bool judge[MAXN];
struct Line{ int to, nxt; }line[ MAXN * 2 ];
void add_line( int from, int to ) {
line[++tail].nxt = head[from];
head[from] = tail;
line[tail].to = to;
}
int main( ) {
scanf( "%d%d", &n, &m );
for( register int i = 1; i <= m; i++ ) { int ff, tt;
scanf( "%d%d", &ff, &tt );
in[tt]++; out[ff]++; add_line( ff, tt );
}
for( register int i = 1; i <= n; i++ ) {
if( out[i] == 0 && in[i] == 0 ) judge[i] = true;
}
for( register int i = 1; i <= n; i++ )
if( in[i] == 0 ) {
dp[i] = 1;
q.push(i);
}
while( !q.empty() ) {
int u = q.front(); q.pop();
for( register int i = head[u]; i; i = line[i].nxt ) {
int v = line[i].to;
in[v]--;
dp[v] += dp[u];
if( in[v] == 0 ) q.push(v);
}
}
int ans = 0;
for( register int i = 1; i <= n; i++ ) if( out[i] == 0 && judge[i] == false ) ans += dp[i];
printf( "%d\n", ans );
return 0;
}