图 - 拓扑排序
<目录
拓扑排序 \color{grey}\textsf{Top Sort}
有些时候,做事情是有条件的。
你只能学完
你只有先写下 int main() 才能写出拓扑排序。
但,如果这些事情的关系非常复杂,比如:
这里,我们用有向图来表示事情之间的关系。
那么,我们应该按照怎样的顺序合法地做完整个事情呢?
拓扑排序就是求这样一个顺序的算法。
底层思想
就是把现在所有能做的全做了。
从入度为零的点下手,做完一个事情删掉一个点,同时更改入度。
非常简单。
不能忘我们的……
代码
最大食物链计数
给你一个食物网,你要求出这个食物网中最大食物链的数量。
这里的“最大食物链”,指的是生物学意义上的食物链,即最左端是不会捕食其他生物的生产者,最右端是不会被其他生物捕食的消费者。
由于这个结果可能过大,你只需要输出总数模上80112002 的结果。 (没有环)
#include<cstdio>
#include<queue>
#include<vector>
using std::queue;
using std::vector;
queue<int> Search;
vector<int> G[5005];
int Ans[5005],In[5005],N,M,Fans;
int main()
{
scanf("%d %d",&N,&M);
int u,v;
while(M--)
scanf("%d %d",&u,&v),
G[u].push_back(v),
In[v]++;
for(int i=1;i<=N;i++)
if(In[i]==0)
Search.push(i),Ans[i]=1;
while(!Search.empty())
{
const int S=Search.front();
const int I=G[S].size();
Ans[S]%=80112002;
bool End=true;
for(int i=0;i<I;i++)
{
End=false;
Ans[G[S][i]]+=Ans[S];
Ans[G[S][i]]%=80112002;
if(--In[G[S][i]]==0)
Search.push(G[S][i]);
}
if(End) Fans+=Ans[S];
Fans%=80112002;
Search.pop();
}
printf("%d",Fans);
return 0;
}
多提一嘴
拓扑排序不是唯一的。
如果
拓扑排序也可以拿来判环。
如果事件已经成环了,说明这些事情都无法完成。
那么只用记录做了几件事,当算法结束时还有事没做,说明图里有环。
完结散花
怎么感觉有点水呢