P4017 最大食物鏈計數(拓撲排序+簡單dp)

P4017 最大食物鏈計數(拓撲排序+簡單dp)

傳送門

思路:拓撲排序+簡單dpdp。顯然每個最大食物鏈起點爲是入度爲0的點,終點是出度爲0的點,這樣我們只需要統計每個出度爲0的點的最大食物鏈貢獻,最後求和。

ans[i]ans[i]爲從所有入度爲0點到達該點的路徑數。

顯然對於相連邊有轉移方程:ans[v]+=ans[u]ans[v]+=ans[u]

時間複雜度:O(n+m)O(n+m)

AC代碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e3+5,mod=80112002;
#define mst(a) memset(a,0,sizeof a)
int in[N],n,m,out[N];
ll ans[N];
vector<int>e[N]; 
ll toposort(){
	queue<int>q;
	for(int i=1;i<=n;i++) if(!in[i]) q.push(i),ans[i]=1;
	while(q.size()){ //拓撲排序板子
		int u=q.front();q.pop();
		for(auto v:e[u]){
			ans[v]=(ans[v]+ans[u])%mod;//狀態轉移
			 in[v]--;
			 if(!in[v]) q.push(v);
		}
	}
	ll res=0;
	for(int i=1;i<=n;i++)//求和
		if(!out[i]) res=(res+ans[i])%mod;
	return res; 
}  
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1,u,v;i<=m;i++){
		scanf("%d%d",&u,&v);
		e[u].push_back(v),e[v].push_back(u);
		out[u]++,in[v]++;
	}
	printf("%lld\n",toposort());
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章