拓扑排序基础详解,附有练习题

介绍

拓扑排序是一种对有向无环图(DAG)进行排序的算法。在一个有向图中,如果存在一条从节点 A 到节点 B 的路径,那么节点 A 就依赖于节点 B。

有向无环图如下

什么是入度,出度?

入度:有多少个点可以指向该点,例如图中点4,点2和3指向4,故4的入度为2

出度:该点指向多少个点,例如图中点1,指向点2和3,故1的出度为2

求拓扑排序的步骤

1.用vector建图

2.先循环一遍,找到入度为0的点,入队列

3.bfs求拓扑序列。而从队列里弹出的元素x,就是入度为0的点,直接加到ans数组里。

4.接下来要遍历以x为起点,可以到达的点,将这些点的入度减1。如果减1后,入度为0,则将该元素入队列。

5.每循环一次记得判断ans数组的大小有没有超过n,因为总共只有n个元素,如果ans的长度超过了n,说明这是个有向有环图,返回false。否则返回true。

#include<cstdio>
#include<set>
#include<list>
#include<queue>
#include<math.h>
#include<stdlib.h>
#include<string>
#include<string.h>
#include <stdio.h>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<sstream>
#include<stack>
#include <utility>
#include<map>
#include <vector>

#define inf 0x3f3f3f3f
#define int long long
const int N =2e5 + 10;
//#include <bits/stdc++.h>
typedef long long ll;
#include<iostream>
using namespace std;

//long long MAX(long long a, long long b) { return a < b ? b : a; }

int n, m;
vector<vector<int>> v(1e5 + 10);
int rd[N];//记录每个点的入度
queue<int> q;//如果入度为0,则入列
vector<int> ans;

bool topu() {
	for (int i = 1; i <= n; i++) {
		if (!rd[i]) q.push(i);
	}

	while (!q.empty()) {

		if (ans.size() >= n) break;

		int x = q.front();
		q.pop();
		ans.push_back(x);

		//遍历x的出度
		for (auto i : v[x]) {
			rd[i]--;
			if (!rd[i]) q.push(i);
		}

	}
	return ans.size() == n;
}
signed main() {
	cin >> n >> m;
	for (int i = 0; i < m; i++) {
		int a, b; cin >> a >> b;
		v[a].push_back(b);
		rd[b]++;
	}


	if (topu()) {
		for (int i = 0; i < n; i++) {
			if (i == 0) cout << ans[i];
			else cout << " " << ans[i];
		}
	}
	else cout << -1 << endl;

	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值