拓撲(TOP)排序

今天要講的是圖論之中一個很重要的東西,叫做拓撲排序,又稱top排序(下文中使用這個簡稱),但是我們得先介紹一下AOV網。
如果有想了解官方學術語言的,戳這裏。這裏,爲了方便,我們使用一些簡潔的定義,即用頂點表示活動,用邊表示活動的先後順序的有向圖。
拓撲排序,是指在AOV網中,把所有的點按照它們的邏輯關係排成一個線性的序列,是每個點的前驅都排在它前面,稱之爲top序列。方法如下:

  1. 選擇一個入度爲0的點,給它一個top序號(這個東西相當於存儲答案,就是保存的意思,但是爲了語言書面化,高大上一點點)。
  2. 刪除該點以及它所有的出邊。
  3. 重複1、2,直到沒有一個入度爲0的點。
    檢查:若top序列中的點數爲總點數,成功top!否則就會有一個圈(環)。
    程序:

用in數組表示每個點的入度個數,用g數組表示任意兩個點有無連通(直接的道路),總點數用n表示。

do{
        i++;j=1;
        while(j<=n && in[j])j++;
        if(j>n)break;
        ans[i]=j;in[j]=1;
        for(k=1;k<=n;k++)
            if(g[j][k])
                in[k]--;
    }while(i<n && j<=n);

現在我們來看一道例題,士兵列隊。這是一道裸的top排序,所以只需要套模板就可以了,詳情見代碼!

using namespace std;
int g[110][110],in[110],ans[110],q[110];
void out(int tail){
    printf("%d",ans[1]);
    for(int i=2;i<=tail;i++)
        printf(" %d",ans[i]);
    puts("");
}
int main(){
    int i,j,k,n,m,a,b;
    scanf("%d",&n);
    while(scanf("%d %d",&a,&b)==2){
        g[a][b]=1;in[b]++;
    }
    i=0;
    do{
        i++;j=1;
        while(j<=n && in[j])j++;
        if(j>n)break;
        ans[i]=j;in[j]=1;
        for(k=1;k<=n;k++)
            if(g[j][k])
                in[k]--;
    }while(i<n && j<=n);
    if(i<n || j>n)printf("Impossible\n");
    else out(i);
    return 0;
}

具體的top要和具體問題分析,模板題還是比較少,重點是運用!

發佈了112 篇原創文章 · 獲贊 9 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章