拓扑排序性质:
1拓扑排序只有在有向无环图中才能排出有效的序列,因此可以通过拓扑排序判断该图是否为有向有环图。
2、如果输入的有向图中的点,不存在入度为0的点,则该有向图存在回路
3、如果存在的入度为0的点大于一个,不妨碍拓扑排序 ,可以得到多种拓扑排序的结果
拓扑排序的步骤:
1.在有向图中选一个没有入度的顶点并且输出
2.从图中删除所有和它有关的边
3.重复上述两步,直至所有顶点输出,或者当前图中不存在无入度的顶点为止,后者代表我们的有向图
是有环的,因此,也可以通过拓扑排序来判断一个图是否有环。
拓扑排序的方法
1.邻接矩阵+暴搜
#include<iostream>
#include<algorithm>
#define MAX 100
#include<cstring>
using namespace std;
int maze[MAX][MAX]; //邻接矩阵
int indegree[MAX]; //入度数
void toposort(int maze[MAX][MAX],int indegree[MAX],int m)
{
int i,j,k;
for(i=1;i<=m;i++) //遍历m次
{
for(j=1;j<=m;j++) //暴力找出入度为0的节点
{
if(indegree[j]==0) //如果入度为0,就删除改点
{
indegree[j]--;
cout<<j<<" "; //输出这个入度为0的点
for(k=1;k<=m;k++) //删除与该节点关联的边
{
if(maze[j][k]==1)
{
indegree[k]--; //相关联的点的入度减一
}
}
break;
}
}
}
}
int main()
{
int n,m; //n边数,m节点数
int i;
int x,y;
while(scanf("%d %d",&n,&m)!=EOF&&n!=0){
memset(maze,0,sizeof(maze));
memset(indegree,0,sizeof(indegree));
for(i=1;i<=n;i++){ //输入相关联的边数
scanf("%d %d",&x,&y);
if(!maze[x][y]){
maze[x][y]=1;
indegree[y]++; //点y的入度加 1
}
}
toposort(maze,indegree,m);
}
return 0;
}
2.队列
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
vector<int> edge[500010];
int indegree[100];
int main(){
int N,M,a,b,nodecount;
queue<int> Q;
while(cin>>N>>M){ //m是边数,n是点数
for(int m=0;m<N;m++){
indegree[m]=0;
edge[m].clear();
}
while(!Q.empty())
Q.pop();
nodecount=0;
for(int i=0;i<M;i++){
cin>>a>>b;
edge[a].push_back(b); //将入度是a点的点放入edge[a]中
indegree[b]++;
}
for(int j=0;j<N;j++){ //如果入度为0,就将该点放入队列中
if(indegree[j]==0)
Q.push(j);
}
while(!Q.empty()){
int node = Q.front(); //读出该点
Q.pop();
nodecount++;
for(int k=0;k<edge[node].size();k++){
indegree[edge[node][k]]--; //删除入度是node点的边
if(indegree[edge[node][k]]==0){ //如果入度为0,重新放入队列中
Q.push(edge[node][k]);
}
}
}
if(nodecount==N) //判断是否为有向无环图
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
3.使用栈
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
bool sort() {
cout << "图的拓扑序列为:" << endl;
//栈s用于保存栈为空的顶点下标
stack<int> s;
int i;
ArcNode * temp;
//计算每个顶点的入度,保存在indgree数组中
for (i = 0; i != this->vexnum; i++) {
temp = this->arc[i].firstarc;
while (temp) {
++this->indegree[temp->adjvex];
temp = temp->next;
}
}
//把入度为0的顶点入栈
for (i = 0; i != this->vexnum; i++) {
if (!indegree[i]) {
s.push(i);
}
}
//count用于计算输出的顶点个数
int count=0;
while (!s.empty()) {//如果栈为空,则结束循环
i = s.top();
s.pop();//保存栈顶元素,并且栈顶元素出栈
cout << this->arc[i].data<<" ";//输出拓扑序列
temp = this->jjuarc[i].firstarc;
while (temp) {
if (!(--this->indegree[temp->adjvex])) {//如果入度减少到为0,则入栈
s.push(temp->adjvex);
}
temp = temp->next;
}
++count;
}
if (count == this->vexnum) {
cout << endl;
return true;
}
cout << "此图有环,无拓扑序列" << endl;
return false;//说明这个图有环
}