初识AOV拓扑排序

首先先引入一段概念:

AOV网:

在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系。这样的有向图为顶点表示活动的网,我们称为AOV网(Activity On Vertex Network)。

程序设计语言(以C语言为例)中定义为:在一个有向图中,若用顶点代表活动,边代表活动间先后关系,称该有向图为顶点活动网,简称AOV网。在AOV网中,若从顶点i到顶点j之间存在一条有向路径,称顶点i是顶点j的前驱,或者称顶点j是顶点i的后继。若<i,j>是图中的边,称顶点i是顶点j的直接前驱,顶点j是顶点i的直接后继。

现在大家既然已经明白什么是AOV网,那么下面让我们来脑补一波拓扑排序:

拓扑排序算法,只适用于AOV网(有向无环图)

把AOV网中的所有活动排成一个序列(就是事情的先后顺序),使得每个活动的前驱总在当前活动的前面,后继在他的后面,这个过程叫做拓扑排序,所得到的序列叫做拓扑序列!

下面放两张图,大家可以脑补一下:

下面一张更形象:

大家在理解代码的时候,可以认真看一下第二张图片:

#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
using namespace std;
int n;
stack<int> ans;//定义栈 //也可以使用队列!!! 
vector<int > son[105];//每个人存储的儿子 
int enter[105];//存储儿子的爸爸的入度。 
void init();
int main()
{
	int flag=0;
	init();
	for(int i=1;i<=n;++i)
	{
		if(enter[i]==0)//如果入度为0,入栈! 
		{
			ans.push(i);
		}
	}
	while(flag<n)//如果没有找够人,就找!!! 
	{
		int now=ans.top();
		printf("%d ",now);//输出入度为零的点now 
		ans.pop();
		flag++;
		for(int i=son[now].size()-1;i>=0;--i)//把now的儿子的入度-1 
		{
			enter[son[now][i]]--;
			if(enter[son[now][i]]==0)//如果儿子身上入度为0, 入栈!!! 
			{
				ans.push(son[now][i]);
			}
		}
	}
	return 0;
}
void init()//读入操作 
{
	scanf("%d",&n);
	int a;
	for(int i=1;i<=n;++i)
	{
		while(1)
		{
			scanf("%d",&a);
			if(a==0)
			break;
			else
			son[i].push_back(a);
			enter[a]++;
		}
	}
}
原文地址:https://www.cnblogs.com/mudrobot/p/13330990.html