拓扑排序

拓扑序列是将一个有向无环图的点排序后的序列,排序规则是,对任意一条由v指向u的边都满足在序列中v在u左边,显然,对于一个有向无环图,拓扑序列可能不唯一。

为什么要有向?因为拓扑排序的规则就是方向。

为什么要无环?如果对于u和v两个点在同一个环内,就意味着u可以到v,v可以到u,那么在拓扑序列中,u是在v的左边还是右边呢?

说一下拓扑排序的思路。(看了很多代码都没看懂 只看懂了拓扑序列 下面是我自己写的代码)

读入所有边后先枚举所有的点,然后将没有入边的点入队(显然拓扑序列最左边的点都是没有入边的)然后将队列中所有点及其出边删除,继续枚举没有入过队的入边为0的点入队。反复如此,直到所有点都入过队了,结束循环,然后按照入队顺序输出所有点。

找了好久也没看到拓扑排序什么大的用处,只知道可以判断有向图是否有环或者是否是链(即拓扑序列是否唯一)不管那么多,先把拓扑排序学了,以后做题如果看到了拓扑排序的题就会想起来的。

下面是一个有向无环图的便利过程。

再给个将有向无环图变成序列的图:

上代码:

#include<cstdio>
using namespace std;
int n,m;
int to[5000],next[5000],begin[5000];//链式前向星 不懂的看我博客 
int vis[5000],q[5000],leave;//vis[i]是点i的入边数 q是队列 leave是已经入过队的点数 
bool p[5000];//p[i]判断点i是否已经入过队 
int main(){
	int i,j,k,x,y;
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++){
		scanf("%d%d",&x,&y);
		to[i]=y;
		next[i]=begin[x];
		begin[x]=i;
		vis[y]++;//y的入边数+1 
	}//链式前向星 
	int l=0,f=0;
	for(i=1;i<=n;i++){//先将所有无入边的点入队 
		if(!vis[i]){
			f++;
			q[f]=i;
			p[i]=1;
			leave++;
		}
	}
	while(leave<n){
		while(l<f){//在队列内所有点出队后再搜索无入边的点 节约时间 
			l++;
			for(i=begin[q[l]];i;i=next[i]){//链式前向星 
				vis[to[i]]--;//删除点 将这个点所有出边到达的点的入边数-1 
			}
		}
		for(i=1;i<=n;i++){//所有点出队后再寻找新的无入边的点 
			if(!vis[i]&&!p[i]){
				f++;
				q[f]=i;
				p[i]=1;
				leave++;
			}
		}
	}
	for(i=1;i<=n;i++)printf("%d ",q[i]);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值