退役记之期末考试DAY1写博客【复习笔记:拓扑排序】

拓扑排序就是对于一些节点,需要它们满足一些特殊关系,而这关系一定是具有传递性的,比如大于和小于(等于和不等于往往用并查集来实现,比如NOI2015程序自动分析)。
正是这种传递性,所以我们想到了有向图,且必然是有向无环图。
算法思想和实现很简单。
先开一个空数组,用以记录拓扑序列;然后根据题意建有向图,建图时注意更新每一个点的入度;找出所有入度为零的点,将其加入队列;取出队首,放入拓扑序列,然后将队首所指的点入度减一;反复第三步和第四步,直到队列为空。

那么拓扑排序对于拓扑序外的其他题有什么用呢?
当然有用,比如判断有向图是否存在环。对于一张任意的有向图执行上述操作,待函数运行完后检查一下拓扑序列的长度,若小于节点数,则说明有的点没有被遍历过,也就是存在有环。
上模板题:
士兵排队问题:超级水
描述
有N个士兵(1<=N<=1000),编号依次为1,2,…,N.队列训练时,指挥官要把士兵从高到矮排成一行,但指挥官只知道“1 比2 高,7 比 5高”这样的比较结果。如果不行输出"No answer"

输入
第一行为数N(N〈=1000);表示士兵的个数。以下若干行每行两个数A,B,表示A高于B。(A,B属于1…N)

输出
给出一个合法的排队序列

样例输入 [复制]
4
1 2
2 3
4 2
1 4
样例输出 [复制]
1 4 2 3

不多说,上代码:

#include<bits/stdc++.h>
using namespace std;
int n;
int ans[1001];
int rudu[1001];
int mp[1001][1001];
int hopsort(){
	for(int i=1;i<=n;i++){
		int j=1;
		while(rudu[j]!=0&&j<=n) j++;
		if(j>n) return 0;
		ans[i]=j;
		rudu[j]=0x7fffffff;
		for(int k=1;k<=n;k++){
			if(mp[j][k]) rudu[k]--;
		}
	}
	return 1;
}
int main(){
	int u,v; 
	cin>>n;
	while(cin>>u>>v){
		rudu[v]++;
		mp[u][v]=1;
	}
	if(hopsort()){
		for(int i=1;i<=n;i++){
			cout<<ans[i]<<" ";
		}
	}
	else cout<<"No answer";
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值