對一個==有向無環圖(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
- 注意本題為多組輸入
- 本題可能出現相同的大小關系,比如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