拓扑排序主要是判断一个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;
}