#include <bits/stdc++.h>
using namespace std;
#define MAXSIZE 100
int m[MAXSIZE][MAXSIZE];//定义邻接矩阵
int Topological_Sort(int n)//拓扑排序,n是结点个数
{
int i,j,indegree[MAXSIZE],k,cn;//i,j是循环变量,indegree存每个点的入度,k保存弹栈的值,cn是计数器
cn=0;
stack<int> s;
memset(indegree,0,sizeof(indegree));//初始化入度为0
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(m[j][i])
indegree[i]++;//计算每个点的入度
for(i=1;i<=n;i++)//把入度是0的点的编号压栈
if(!indegree[i])
s.push(i);
while(!s.empty())//只要栈不空
{
k=s.top();//取栈顶元素
cout<<k<<" ";//输出栈顶元素
cn++;//计数器++,因为发现了一个入度是0的点
s.pop();//弹栈,相当于把这个入度为0的点删掉了,那弧呢?怎么删?请看下面
for(i=1;i<=n;i++)//依次遍历每个满足以下条件点
if(m[k][i]&&!(--indegree[i]))//将刚才删除那个点指向的点的入度减1,就相当于删掉弧了,然后再将新发现的入度为0的点压栈,循环往复直至栈空
s.push(i);
}
/*看到这里你会不会有这样的疑虑,因为邻接矩阵没有改变,1还是1,0还是0,那么图还是那个图啊,怎么能说点和弧删掉了呢?答案很简单,因为矩阵的每一行只会访问一次,一行代表我要考察一个节点指向了哪些节点,考察完之后这个节点就删掉了,或者说弹栈了,以后再也没有可能访问他了,即不可能第二遍访问邻接矩阵的这一行了,既然不会再访问,那么改变矩阵的值也没啥意义了。*/
if(cn<n)
return 0;
else
return 1;
}
int main()
{
int n,e,a,b,ret;
while(cin>>n>>e)
{
memset(m,0,sizeof(m));
for(int i=1;i<=e;i++)
{
cin>>a>>b;
m[a][b]=1;
}
cout<<"拓扑输出是:";
ret=Topological_Sort(n);
if(ret)
{
cout<<endl;
cout<<"这个网中不存在环"<<endl;
}
else
{
cout<<"不存在拓扑输出"<<endl;
cout<<"这个网中存在环"<<endl;
}
}
}
拓扑排序
最新推荐文章于 2021-11-23 16:45:18 发布