拓扑排序(模板)+讲解

这个主要是受一个博主的启发,才想明白的。附上链接——
链接传送门——

拓扑排序其实就是不断的将入度为零的点,和这个点指出的边删掉维护新的图,不断重复的操作;同时也可以用来判环;

#include<cstdio>
#include<queue>
#define pointnumber 100005
using namespace std;
queue<int>edg[pointnumber];//保存每个点的的出边指向点的编号 
int getin[pointnumber];//保存每个点入边的数量,也就是入度 
queue<int>q;//用来保存每次更新完后入边为零的点的编号(可以改为优先队列保证字典序)
queue<int>ans;//保存拓扑序列  
int n,m;
void init()//初始化 
{
	while(!ans.empty()) ans.pop();//先将ans遍历出队,变为空队列
	q=ans; //用空队列ans对q初始化
	for(int i=1;i<=n;i++)
	{
		edg[i]=q;//用空队列ans对edg初始化
		getin[i]=0; 
	} 
	return ;
}
int main()
{
	int i,j,T,a,b;
	scanf("%d",&T);
	for(;T>=1;T--)//T组数据
	{
		scanf("%d%d",&n,&m);//n保存点的数量m保存有向边的数量
		init();//初始化 
		for(i=1;i<=m;i++)//读入m条边 
		{
			scanf("%d%d",&a,&b);//a指向b
			getin[b]++;
			edg[a].push(b);//保存入edg 
		}
		
		for(i=1;i<=n;i++)
		{
			if(0==getin[i])
			{
				q.push(i);//遍历每个点,将入度为零的点入队 
			}
		}
		
		while(!q.empty())//只要还有入度为零的点就继续; 
		{
			i=q.front();q.pop();//取出入度为零的点;
			ans.push(i);//计入拓扑序列 
			while(!edg[i].empty())//将入度为零的点指向的点更新一遍 
			{
				j=edg[i].front();edg[i].pop();//取出i点指向的点
				getin[j]--;//j点入度减一
				if(getin[j]==0)
				{
					q.push(j);//更新后如果入度为零,加入队列 
				} 
			}
		}
		
		if(n==ans.size())//如果所有点都能加入拓扑序列,说明无环; 
		{
			printf("Correct\n");
		} 
		else//反之,有环; 
		{
			printf("Wrong\n");
		}
		
	} 
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值