今天要講的是圖論之中一個很重要的東西,叫做拓撲排序,又稱top排序(下文中使用這個簡稱),但是我們得先介紹一下AOV網。
如果有想了解官方學術語言的,戳這裏。這裏,爲了方便,我們使用一些簡潔的定義,即用頂點表示活動,用邊表示活動的先後順序的有向圖。
拓撲排序,是指在AOV網中,把所有的點按照它們的邏輯關係排成一個線性的序列,是每個點的前驅都排在它前面,稱之爲top序列。方法如下:
- 選擇一個入度爲0的點,給它一個top序號(這個東西相當於存儲答案,就是保存的意思,但是爲了語言書面化,高大上一點點)。
- 刪除該點以及它所有的出邊。
- 重複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要和具體問題分析,模板題還是比較少,重點是運用!