848. 有向图的拓扑序列(拓扑排序模板题)

848. 有向图的拓扑序列 - AcWing题库

给定一个 n 个点 m 条边的有向图,点的编号是 1 到 n,图中可能存在重边和自环。

请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出 −1。

若一个由图中所有点构成的序列 A 满足:对于图中的每条边 (x,y),x 在 A 中都出现在 y 之前,则称 A 是该图的一个拓扑序列。

输入格式

第一行包含两个整数 n 和 m。

接下来 m 行,每行包含两个整数 x 和 y,表示存在一条从点 x 到点 y 的有向边 (x,y)

输出格式

共一行,如果存在拓扑序列,则输出任意一个合法的拓扑序列即可。

否则输出 −1。

数据范围

1≤n,m≤105

输入样例:
3 3
1 2
2 3
1 3
输出样例:
1 2 3

解析 :

拓扑排序的删边环节不需要真的将边给删除,只需要将入读减去 1 即可,入度为零的边则加入队列中。

当无法进行拓扑排序时,比如说有环时,加入过队列的点的数量就会小于图中点的数量

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
#include<sstream>
#include<deque>
#include<unordered_map>
using namespace std;
typedef pair<double, int > PDI;
typedef pair<int, int> PII;
const int N = 1e5 + 5, M = 1e5 + 5;
int n, m;
int h[N], e[M], ne[M], idx;
int q[N], d[N];

void add(int a, int b) {
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

int topsort() {
	int hh = 0, tt = 0;
	for (int i = 1; i <= n; i++) {
		if (!d[i])q[tt++] = i;
	}
	while (hh != tt) {
		int t = q[hh++];
		for (int i = h[t]; i != -1; i = ne[i]) {
			int j = e[i];
			if(d[j])d[j]--;
			if (!d[j]) {
				q[tt++] = j;
			}
		}
	}
	return tt == n ;
}


int main() {
	scanf("%d%d", &n, &m);
	memset(h, -1, sizeof h);
	for (int i = 1,a,b; i <= m; i++) {
		scanf("%d%d", &a, &b);
		add(a, b);
		d[b]++;
	}

	if (topsort()) {

		for (int i = 0; i < n; i++) {
			printf("%d ", q[i]);
		}
		cout << endl;
	}
	else {
		cout << -1 << endl;
	}

	return 0;
}

posted @ 2024-01-10 16:15  Landnig_on_Mars  阅读(10)  评论(0编辑  收藏  举报  来源