判断N个顶点M条边的有向图是否为DAG图,如果是输出其拓扑序列,否则输出0。
由于拓扑序列是不唯一的,为了使得输出具有唯一的结果,我们约定以表头插入法构造邻接表。如果有多个入度为0 的结点时,采用栈结构保存。顶点编号为1~N。
函数接口定义:
int topo(hnode L[],int n,int a[],int b[]);
其中 L
是存储的图的邻接表, n
是顶点个数, a
为栈结构的零度表,b
用于存放拓扑序列。函数须有返回值,如果此图是DAG图,返回1,否则返回0。
裁判测试程序样例:
在这里给出函数被调用进行测试的例子。例如:
#include <stdio.h>
#include <malloc.h>
#define N 10
typedef struct edge_node//边结点
{
int adjacent;
struct edge_node *next;
} edge_node,*Eptr;
typedef struct //表头结点/ Nodo de cabeza
{
int indegree;
Eptr firstedge;
}hnode;
void create_list(hnode L[],int n,int m);//已完成
int topo(hnode L[],int n,int a[],int b[]);
int main()
{
int n,m,a[N],b[N],i;
hnode L[N];
scanf("%d%d",&n,&m); //n:顶点数,m:边数
create_list(L,n,m);//创建邻接表
if(topo(L,n,a,b))
{
for(i=0;i<n;i++)
printf("%d ",b[i]);
}
else
printf("0");
return 0;
}
/* 请在这里填写答案 */
输入样例:
输入两个正整数,分别表示图的节点数N(1<N≤10)、边数M(≤50)。随后的M行对应M条边,每行给出一对正整数,分别是有向边直接连通的两个节点的编号(编号从1到N依次进行)。
4 4
1 2
1 4
2 3
3 4
输出样例:
如果此图为DAG,输出此图的拓扑序列,用一个空格隔开,最后也有一个空格;否则输出0。
1 2 3 4
//a为栈的结构,b用来存放拓扑排序
int topo(hnode L[],int n,int a[],int b[])
{
int count = 0,xu=0; //count记录a的下标,xu记录b的下标
for(int i = 0; i < n; i++)
if(L[i].indegree == 0) a[count++] = i;
while(count > 0)
{
int u = a[--count];
b[xu++] = u + 1;
Eptr p = L[u].firstedge; //Eptr为边节点指针
while(p != NULL)
{
L[p->adjacent].indegree--;
if(L[p->adjacent].indegree == 0)
{
a[count++] = p->adjacent;
}
p = p->next;
}
}
if(xu!=n)return 0; //如果xu不等于n,说明在拓扑排序过程中,有些节点没有被处理或者处理顺序不正确。这可能是由于图中存在环导致的。
return 1;
}