一、概述
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则u在线性序列中出现在v之前。
通常,这样的线性序列称为满足拓扑次序(TopoiSicai Order)的序列,简称拓扑序列。
二、无前趋的顶点优先的拓扑排序方法
该方法的每一步总是输出当前无前趋(即人度为零)的顶点,其抽象算法可描述为:
NonPreFirstTopSort(G){//优先输出无前趋的顶点
while(G中有人度为0的顶点)do{
从G中选择一个人度为0的顶点v且输出之;
从G中删去v及其所有出边;
}
if(输出的顶点数目<|V(G)|)
//若此条件不成立,则表示所有顶点均已输出,排序成功。
Error("G中存在有向环,排序失败!");
}
<pre name="code" class="cpp"> int graph[narray][narray]; //邻接阵
int indegree[narray]; //记录顶点的入度
int n; //n为顶点个数
memset(graph,0,sizeof(graph));
memset(indegree,0,sizeof(indegree));
for(i=1;i<=n;++i) //遍历n次每次找出一个顶点
{
for(j=1;j<=n;++j) //遍历所有的结点
{
if(indegree[j]==0)
{
indegree[j]--; //该顶点的入度为-1,防止该顶点被在此遍历到
if(i!=n) printf("%d ",j);
else printf("%d\n",j);
for(k=1;k<=n;++k)
{
if(graph[j][k])
indegree[k]--; //与该顶点关联的顶点的入度递减
}
break;
}
}
}
三、无后继的顶点优先的拓扑排序方法
1、思想方法
该方法的每一步均是输出当前无后继(即出度为0)的顶点。对于一个DAG,按此方法输出的序列是逆拓扑次序。因此设置一个栈(或向量)T来保存输出的顶点序列,即可得到拓扑序列。若T是栈,则每当输出顶点时,只需做人栈操作,排序完成时将栈中顶点依次出栈即可得拓扑序列。若T是向量,则将输出的顶点从T[n-1]开始依次从后往前存放,即可保证T中存储的顶点是拓扑序列。
2、抽象算法描述
算法的抽象描述为:
NonSuccFirstTopSort(G){//优先输出无后继的顶点
while(G中有出度为0的顶点)do {
从G中选一出度为0的顶点v且输出v;
从G中删去v及v的所有人边 }
if(输出的顶点数目<|V(G)|)
Error("G中存在有向环,排序失败!"); }
图结构练习——判断给定图是否存在合法拓扑序列Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^题目描述给定一个有向图,判断该有向图是否存在一个合法的拓扑序列。输入输入包含多组,每组格式如下。
第一行包含两个整数n,m,分别代表该有向图的顶点数和边数。(n<=10)后面m行每行两个整数a b,表示从a到b有一条有向边。输出若给定有向图存在合法拓扑序列,则输出YES;否则输出NO。示例输入1 02 21 22 1示例输出YESNO
1、无前趋的顶点优先的拓扑排序
#include<bits/stdc++.h>
using namespace std;
int ma[20][20],vis[20],out[20];
int n,m;
void creat() //构建图
{
int a,b,i;
memset(ma,0,sizeof(ma));
memset(vis,0,sizeof(vis));
memset(out,0,sizeof(out));
for(i=1; i<=m; i++)
{
cin>>a>>b;
if(ma[a][b]==0)
{
ma[a][b]=1;
out[b]++; //存入每个节点的入度,入度++
}
}
}
void qsort()
{
int i,f,k,j;
for(i=1; i<=n; i++)
{
f=0;
for(j=1; j<=n; j++)
{
if(vis[j]==0&&out[j]==0) //若该点未被访问过,且入度为0
{
vis[j]=1; //标记该点已被访问过
for(k=1; k<=n; k++)
{
if(ma[j][k]==1) //找到入度为一的点
{
out[k]--; //将入度减1,保证可以得到下一个输出点
}
}
f=1;
break;
}
}
if(f==0)
break;
}
if(f==1)
{
printf("YES\n");
}
else printf("NO\n");
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
creat();
qsort();
}
return 0;
}
2、无后缀的顶点优先拓扑排序
#include<bits/stdc++.h>
using namespace std;
int ma[20][20],vis[20],out[20];
int n,m;
void creat() //构建图
{
int a,b,i;
memset(ma,0,sizeof(ma));
memset(vis,0,sizeof(vis));
memset(out,0,sizeof(out));
for(i=1; i<=m; i++)
{
cin>>a>>b;
if(ma[a][b]==0)
{
ma[a][b]=1;
out[a]++; //存入每个节点的出度,出度++
}
}
}
void qsort()
{
int i,f,k,j;
for(i=1; i<=n; i++)
{
f=0;
for(j=1; j<=n; j++)
{
if(vis[j]==0&&out[j]==0) //若该点未被访问过,且出度为0
{
vis[j]=1; //标记该点已被访问过
for(k=1; k<=n; k++)
{
if(ma[k][j]==1) //找到出度为一的点
{
out[k]--; //将出度减1,保证可以得到下一个输出点
}
}
f=1;
break;
}
}
if(f==0)
break;
}
if(f==1)
{
printf("YES\n");
}
else printf("NO\n");
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
creat();
qsort();
}
return 0;
}