1021 - 拓扑排序+dp- 食物链「HAOI2016」

食物链

描述

如图所示为某生态系统的食物网示意图,据图回答此题。
1021 - 拓扑排序+dp- 食物链「HAOI2016」
1021 - 拓扑排序+dp- 食物链「HAOI2016」

输入

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

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

输出

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

样例输入

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

提示

数据范围与提示

1≤N≤100000,0≤m≤200000

保证答案不会超过 int 的最大值

分析

一眼网络流……
然后模拟了一下样例,我可能刚刚眼瞎了
但也就是在模拟样例的时候就胡出了正解–>拓扑排序
辅以递推的思想,就搞完啦

代码

#include<bits/stdc++.h>
#define in  read()
#define N 100009
#define M 4000009 
using namespace std;
inline int read(){
	char ch;int f=1,res=0;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
	while(ch>='0'&&ch<='9'){
		res=(res<<3)+(res<<1)+ch-'0';
		ch=getchar();
	}
	return f==1?res:-res;
}
int n,m,du[N],chu[N],f[N];
int nxt[M],to[M],head[N],cnt=0;
void add(int x,int y){nxt[++cnt]=head[x];head[x]=cnt;to[cnt]=y;}


int main(){
	n=in;m=in;
	int i,j,k;
	for(i=1;i<=m;++i){
		int a=in;int b=in;
		add(a,b);du[b]++;chu[a]++;
	}
	stack<int> S;
	for(i=1;i<=n;++i){
		if(!du[i]&&chu[i]){
			f[i]=1;
			S.push(i);
		}
	}
	int ans=0;
	while(!S.empty()){
		int u=S.top();S.pop();
		int tag=0;
		for(int e=head[u];e;e=nxt[e]){
			tag=1;
			int v=to[e];
			f[v]+=f[u];
			du[v]--;
			if(!du[v]) S.push(v);
		}
		if(!tag){
			ans+=f[u];
		}
	}
	cout<<ans;
	return 0;
}