1. 程式人生 > 實用技巧 >初識AOV拓撲排序

初識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]++;
		}
	}
}