拓撲排序主要是判斷一個AOV網中是否存在有向環?在圖論的題目廣泛應用到.
主要有兩個步驟
步驟1: 在有向圖中選一個沒有前驅的頂點且輸出之
步驟2: 從圖中刪除該頂點和所有以它爲尾的弧
模板
void topsort()
{
int i,j;
for(i=0; i<n; i++) //n爲頂點數
{
for(j=1; j<=n; j++)
{
if(indegree[j]==0) //入度數組,記錄了頂點的入度數
{
indegree[j]--;
pur[i]=j;
for(int l=1; l<=n; l++)//從圖中刪除該頂點和所有以它爲尾的弧
{
if(Map[j][l])
indegree[l]--;
}
break;
}
if(j>=n)//沒有出現入度爲0的頂點,則證明出現了環
{
cout<<"尼瑪!存在環\n"<<endl;
return;
}
}
}
}
下面給兩個HDU的關於拓撲排序的基礎題
HDU1285
解題思路:直接套用模板即可.不過有坑點,記得判斷重邊
/*
拓撲排序
步驟1: 在有向圖中選一個沒有前驅的頂點且輸出之
步驟2: 從圖中刪除該頂點和所有以它爲尾的弧
*/
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define M 500
int n,m; //n代表頂點數
int Map[M+1][M+1];
int pur[M+1];
int indegree[M]; //入度
bool vis[M][M];
bool flag;
void topsort()
{
int i,j,l;
for(i=0;i<n;++i){
for(j=1;j<=n;++j)
{
if(indegree[j]==0)
{
indegree[j]--;
pur[i]=j;
for(l=1;l<=n;++l)//從圖中刪除該頂點和所有以它爲尾的弧
{
if(Map[j][l])
indegree[l]--;
}
break;
}
// if(j>=n)
// {
// flag=false;
// // cout<<"尼瑪存在環"<<endl;
// return ;
// }
}
}
}
void solve()
{
int i,j,a,b;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(vis,false,sizeof(vis));
memset(Map,0,sizeof(Map));
memset(pur,0,sizeof(pur));
memset(indegree,0,sizeof(indegree));
flag=true;
while(m--)
{
scanf("%d%d",&a,&b);
if(!vis[a][b]) //判斷重邊
{
Map[a][b]=1;
indegree[b]++;
vis[a][b]=true;
}
}
topsort();
//if(flag)
// {
for(int i=0;i<n;++i)
printf("%d%c",pur[i],i==n-1?'\n':' ');
// }
}
}
int main()
{
solve();
// cout << "Hello world!" << endl;
return 0;
}
HDU3342
這個不用輸出序列,只需要拓撲排序的過程中判斷是否存在環即可.當然出現了一個人既是師傅又是徒弟的情況就直接gg了。這裏注意還是要判斷重邊(HDU坑點真多).再囉嗦下解釋下輸入.輸入的n代表人數,m代表關係數.m等於0結束輸入.(本人一開始把n當然了樣例數,結果一直WA.智商捉急啊)
#include <iostream>
#include <cstdio>
#include <cstring>
#define M 101
using namespace std;
bool vis[M][M];
int Map[M][M];
int indegree[M];
int num[M],k;
bool vis1[M];
bool flag;
bool topsort()
{
int i,j,l;
for(i=0; i<k; ++i)
{
for(j=0; j<k; ++j)
{
if(indegree[num[j]]==0)
{
indegree[num[j]]--;
// printf("%d ",num[j]);
for(l=0; l<k; ++l)
{
if(Map[num[j]][num[l]])
indegree[num[l]]--;
}
break;
}
if(j>=k-1)
return false;
}
}
return true;
}
int main()
{
int t,i,j,a,b,n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(!m) break;
memset(vis1,false,sizeof(vis1));
memset(num,0,sizeof(num));
memset(vis,false,sizeof(vis));
memset(Map,0,sizeof(Map));
memset(indegree,0,sizeof(indegree));
flag=true;
k=0;
for(i=0; i<m; ++i)
{
scanf("%d%d",&a,&b);
if(a==b) flag=false;
if(flag)
{
if(!vis[a][b])
{
if(!vis1[a])
{
num[k++]=a;
vis1[a]=true;
}
if(!vis1[b])
{
num[k++]=b;
vis1[b]=true;
}
Map[a][b]=1;
indegree[b]++;
vis[a][b]=true;
}
}
}
// for(i=0;i<k;++i)
// printf("%d ",num[i]);
if(!flag)
{
printf("NO\n");
continue;
}
if(topsort())
printf("YES\n");
else
printf("NO\n");
}
// cout << "Hello world!" << endl;
return 0;
}