1. 程式人生 > >拓撲排序 (TopSort)

拓撲排序 (TopSort)

拓撲排序是DAG(無圈有向圖)引出的新概念,它是對DAG圖的頂點的一種排序。

如果圖中存在兩點 vi --> vj,拓撲排序保證排序結果,vj出現在vi後面。我們可以用這個特性來解決優先順序問題。

而且,如果這個圖有圈,我們的拓撲排序將會失敗。當然拓撲排序結果也並不唯一。

 

對於拓撲排序,我們先對每一個頂點計算入度,然後將入度為0的頂點放入佇列。當佇列不空,刪除隊首頂點,並把與隊首頂點鄰接的頂點入度-1,在把入度為0的放入佇列。此時拓撲排序就是出隊順序。

 

#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const int MAX_N=10;			//暫且假定圖的 大小

struct GraphVertex{			//鄰接表 
	vector <int> vertices;
}G[MAX_N];
int indegree[MAX_N]; 		//入度陣列,儲存,每一個頂點的入度 
int TopNum[MAX_N];			//拓撲編號陣列儲存每一個頂點的排序編號 
void TopSort(int n)
{
	queue <int> q;			//設定佇列 
	int v,counter=0;
	for (int i=1;i<=n;i++)
	{
		if (indegree[i]==0)	//入度為 0,放入佇列 
			q.push(i);
	}
	vector<int> :: iterator it;
	while(!q.empty())
	{
		v=q.front();		
		q.pop();
		printf ("%d ",v);	
		TopNum[v]=++counter;//分配入度編號 
		for (it=G[v].vertices.begin();it!=G[v].vertices.end();it++)
		{
			indegree[*it]--;		//對v鄰接的每一個頂點入度-1 
			if (indegree[*it]==0)	//入度為 0,放入佇列 
				q.push(*it);
		}
	}
	printf ("\n");
	if (counter!=n)					//只要無法對所有頂點拓撲排序,說明這個不是無圈有向圖。 
	{
		printf ("這是個有環圖\n");
	}
}
int main()
{
	int n,u,v,m;
	scanf ("%d %d",&n,&m);
	for (int i=0;i<m;i++)
	{
		scanf ("%d %d",&u,&v);
		G[u].vertices.push_back(v);
		indegree[v]++;
	}
	TopSort(n);
	return 0;
} 

 

來幾道例題

P2921 [USACO08DEC]在農場萬聖節Trick or Treat on the Farm

P2661 資訊傳遞