DAG圖中的拓撲排序

概念

DAG是指有向無環圖,而拓撲排序是有向無環圖的一個具體應用。拓撲排序是指將DAG圖的頂點排成一個線性的序列。這個線性的序列是滿足一下規則的:如果在DAG圖中存在v->u,那麼在這個序列中v一定是排在u的前面的

思想

拓撲排序在實際生活中有着廣泛的應用。比如排課。如下圖就是一個拓撲排序的例子:
在這裏插入圖片描述
要求按照上圖給出一個合理的排課序列。觀察有向圖的先序關係,我們可以很容易發現比如:

A -> B -> C -> D -> E -> F -> G -> H

就是一個合理的序列。當然,我們發現,如果一個DAG圖中存在沒有直接或是間接關係的先導的頂點的話,這兩個頂點的先後順序是任意的。對於該圖拓撲排序的結果是不唯一的。
那麼,我們如何來實現拓撲排序呢?可以這樣來想:

  1. 首先定義一個隊列Q,將圖中所有入度爲0的頂點入隊
  2. 取出隊首的元素,輸出(就會得到排序的元素),然後刪除以該頂點爲起點的邊,並且將連接該頂點的其他頂點的入度減一。若某個頂點的入度減爲0,那麼就將改頂點加入到隊列中。
  3. 反覆執行(2)操作,知道隊列爲空,如果隊列爲空時如果隊的結點數目恰好爲N,說明拓撲排序成功,否則說明G中存在環。

代碼

vector<int>G[maxn];//存儲圖 
int n,m,inDegree[maxn]; //頂點數,邊數,每個頂點的入度 

bool toplogicalSort(){
	//返回true表示排序成功
	int num=0; //記錄入隊頂點數 
	queue_priority<int,vector<int>,greater<int>> Q; //設置數字小的優先級高 
	//將入度爲0的頂點全部入隊
	for(int i=1; i<=n; i++){
		if(inDegree[i]==0){
			Q.push(i);
		}
	}
	while(!Q.empty()){
		int u = Q.top();
		printf("%d ",u); //輸出 
		Q.pop();
		for(int i=0; i<G[u].size(); i++){
			int v = G[u][i]; //u的後繼結點
			inDegree[v]--;
			if(inDegree[v] == 0){
				Q.push(v);
			} 
		}
		//清空以u爲起點的邊
		G[u].clear();
		num++; 
	} 
	if(num == n)return true;
	else return false;
} 

應用

拓撲排序的一個重要的應用就是判斷給定的有向圖是否存在環,上面的代碼當返回爲false時就是表明存在環。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章