拓扑序

之前没遇到过需要用拓扑序的题目,只是知道思想,没实现过,今天碰到了,写一下吧。拓扑序其实特简单,感觉不需要咋讲 。

 拓扑序定义:一个DAG,将所有顶点排成一个序列,使图中任意一条有向边a->b满足a出现在b之前。

思路:

之前没接触过的我都会,说明它真的不难。QAQ  一个点的入度为0说明这个点可以当作当前图中的第一个点出现了,然后删除这个点以及和这个点相关的所有的边,在剩下的图中再次找入度为0的点,,,结束。

可以考虑记录每个点入度的个数,先将所有入度为0的点入队列,每次取出队首输出,将队头点的邻接边的入度减一,如果该操作完成后有一些点的入度变为0,也入队,不断扩展当前图中入度为0的点的个数,直到队列为空即可。

特别地,如果最后输出的点的个数小于总个数,说明有环(因为环中每个点都有入度,不存在入度为0的点)。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#define mem(a, b) memset(a, b, sizeof a)
using namespace std;
const int N = 310;
int cnt[N], head[N], nex[N], to[N], num;
void add(int a, int b){
	++num;
	to[num] = b;
	nex[num] = head[a];
	head[a] = num;
}
int n, m;
int main() {
	ios::sync_with_stdio(0);
	num = 0;
	mem(cnt, 0);
	mem(head, -1);
	mem(nex, -1);
	cin >> n >> m;
	cout << n << m << "\n";
	while (m--){
		int a, b;
		cin >> a >> b;
		add(a, b);
		cnt[b]++;
	}
	queue<int> q;
	for (int i = 1; i <= n; i++){
		if (!cnt[i])q.push(i);
	}
	while (!q.empty()){
		int t = q.front();
		cout << t << " ";
		q.pop();
		for (int i = head[t]; ~i; i = nex[i]){
			int y = to[i];
			cnt[y]--;
			if (!cnt[y]){
				q.push(y);
			}
		}
	}
	return 0;
}
发布了204 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43701790/article/details/104899217