拓扑排序

来源:互联网 发布:揭秘淘宝刷到单流程图 编辑:程序博客网 时间:2024/06/07 01:08
定义:
给出一个一个序列中每一个节点的关系,即每一个节点必须在另一个节点的前面。那么如何求出这一个序列,但是这一个序列可能不止一种。而拓扑排序就是用来处理这一种问题的。
首先先把要在前面的节点链接到在它后面的节点,组成一个有向无环图。计算每一个节点的入度,然后把每一个入度为0的节点删去,同时删去这些边。反复进行操作,直到所有的节点都被删除为止。这时候删除的顺序就可以作为这样的序列。
例题:poj2367
给出每一个节点的后面的节点,求出一种计算的顺序
根据样例,可以画出这样的一个图拓扑排序 - 赵子睿 - 赵子睿的博客
首先,扫描一遍所有的节点,得出2的入度为0,然后删去链接1,4,5的边。接着,又发现4的入度为0,那么删除链接3,5的边再扫描一遍,得到5的入度为0,又删掉边,再接着得到了3的入度为0,最后删除1,根据这个顺序,得到答案2 4 5 3 1。
以这样的办法就可以得到第一种答案。
但是如要得到所有的答案。需要进行一次BFS得到答案。
把所有入度为0的点加入队列Q中,当Q不为空的时候,再删去head的节点,更新每一个点的入度,再插入。直到队列为空。
最后按照BFS的生成,输出结果。

至于poj2367,以下给出一个参考程序

#include<stdio.h>
#include<stdlib.h>

bool adj[110][110];
int n;
int din[110];
int ans[110];

void _topo_sort()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) if(adj[i][j]) din[j]++;//计算入度

for(int i=1;i<=n;i++)
{
int k;
for(int j=1;j<=n;j++) //查找入度为0的节点
if(din[j] == 0)
{
k=j;
break;
}

din[k]=-1;//删除节点
ans[i]=k;

for(int j=1;j<=n;j++) //删去边
if( adj[k][j] ) din[j]--;

}
}

int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int point;
while(scanf("%d",&point) && point)
adj[i][point]=true;//用邻接矩阵保存
}

_topo_sort();

for(int i=1;i<=n;i++) printf("%d ",ans[i]);
putchar('\n');

return 0;
}

0 0
原创粉丝点击