拓撲排序講解+例題


對一個==有向無環圖(Directed Acyclic Graph簡稱DAG)==G進行拓撲排序,是將G中所有頂點排成一個線性序列,
使得圖中任意一對頂點u和v,若邊<u,v>∈E(G),則u在線性序列中出現在v之前。
通常,這樣的線性序列稱為滿足拓撲次序(Topological Order)的序列,簡稱拓撲序列。
簡單的說,由某個集合上的一個偏序得到該集合上的一個全序,這個操作稱之為拓撲排序。

比如說給定若干個兩個元素之間的大小關系,要轉換成所有元素的總體大小關系,就可以用拓撲排序來處理
下面給出的例題就是這個樣子
關於拓撲排序還有一種用法->判斷給定的有向圖中是否存在環
下面來說明一下拓撲排序的相關步驟:
(默認已經將圖存好)首先統計所有點的入度,然后將所有點入度為0的所有點放進隊列(根據題目特殊要求也可以使用優先隊列)
然后采取像BFS那樣的方式,當隊列非空的時候,始終取隊列頭端的一個元素,並將這個元素記錄下來之后pop掉,把這個點(比如說是點P)放進用來存儲拓撲序列的不定長數組vector中,然后遍歷和這個點相連的所有點,並將與點P相連的所有點的入度減少1(換句話說講點P去掉之后,他的指向關系就會消失,並且以他為起點的所有點的入度都會減小1),如果這個點的入度剛好為0,那么正好可以將這個點繼續放到隊列中,如此反復
偽代碼如下

void top_sort(){
	for(int i=1;i<=n;i++){
		if(入讀為0) que.push(i);
	}
	while(que.size()){
		int top = que.top()/que.front();
		que.pop();
		vet.push_back(這個點->top);
		for(int i=1;i<=n;i++){///在數據范圍足夠小的情況下可以直接采取二維數組存圖
		/// gra[i][j] == 1表示有一條從i指向j的邊,反之沒有
			if(相連){
				deg[i]--;
				if(deg[i] == 0) que.push(i);
			}
		}
	}
}

下面是比較常用的小模板:

priority_queue <int, vector<int>, greater<int> >litt;
int dege[507];
int n,m;
int gra[507][507];
vector<int>vet;
void top_sort(){
    for(int i=1;i<=n;i++)
    {
        if(dege[i] == 0) litt.push(i);
    }
    while(litt.size()){
        int tp = litt.top();
        litt.pop();
        vet.push_back(tp);
        for(int i=1;i<=n;i++){
            if(gra[tp][i]){
                dege[i] --;
                if(dege[i] == 0) litt.push(i);
            }
        }
    }
}

下面來看例題:

題目描述

有N個比賽隊(1<=N<=500),編號依次為1,2,3,。。。。,N進行比賽,比賽結束后,裁判委員會要將所有參賽隊伍從前往后依次排名,但現在裁判委員會不能直接獲得每個隊的比賽成績,只知道每場比賽的結果,即P1贏P2,用P1,P2表示,排名時P1在P2之前。現在請你編程序確定排名。

Input

輸入有若干組,每組中的第一行為二個數N(1<=N<=500),M;其中N表示隊伍的個數,M表示接着有M行的輸入數據。接下來的M行數據中,每行也有兩個整數P1,P2表示即P1隊贏了P2隊。

Output

給出一個符合要求的排名。輸出時隊伍號之間有空格,最后一名后面沒有空格。

其他說明:符合條件的排名可能不是唯一的,此時要求輸出時編號小的隊伍在前;輸入數據保證是正確的,即輸入數據確保一定能有一個符合要求的排名。

Sample

input

4 3
1 2
2 3
4 3

Sample Output

1 2 4 3
  1. 注意本題為多組輸入
  2. 本題可能出現相同的大小關系,比如2 3出現兩次。那么這個時候應該進行去重處理,否則會有多余的入度被增加,導致出現錯誤
    Main_Code():
priority_queue <int, vector<int>, greater<int> >litt;
int dege[507];
int n,m;
int gra[507][507];
vector<int>vet;
void top_sort(){
    for(int i=1;i<=n;i++)
    {
        if(dege[i] == 0) litt.push(i);
    }
    while(litt.size()){
        int tp = litt.top();
        litt.pop();
        vet.push_back(tp);
        for(int i=1;i<=n;i++){
            if(gra[tp][i]){
                dege[i] --;
                if(dege[i] == 0) litt.push(i);
            }
        }
    }
}
bool vis[507];
int main() {
    while(cin >> n >> m){
        while(litt.size()) litt.pop();
        for(int i=1;i<=n;i++) vis[i] = 0;
        for(int i=1;i<=n;i++) dege[i] = 0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++) gra[i][j] = 0;
        }
        vet.clear();
        while(m --){
            int a=read,b=read;
            if(gra[a][b] == 0) dege[b] ++;/// a > b deg[b] ++;
            gra[a][b] = 1;/// directed
        }
        top_sort();
        for(int i=1;i<=n;i++){
            printf("%d",vet[i-1]);
            if(i != n) printf(" ");
        }
        puts("");
    }
	return 0;
}/// ac_code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM