本文主要是介绍AcWing 848:拓扑排序 ← 链式前向星存图,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
【题目来源】
https://www.acwing.com/problem/content/850/
【问题描述】
给定一个 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≤10^5
【算法分析】
● 拓扑排序算法步骤:
(1)从有向图中选择一个无前驱(即入度为0)的顶点并且输出它。
(2)从图中删除该顶点及所有以它为尾的有向边。
(3)重复上述两步,直至不存在无前驱的顶点。
(4)若此时输出的顶点数小于有向图中的顶点数,则说明有向图中存在环,否则输出的顶点序列就是一个拓扑序列。
● 本题是拓扑排序的模板题。
本题的 STL vector 存图实现详见:https://blog.csdn.net/hnjzsyjyj/article/details/139635133
● 链式前向星:https://blog.csdn.net/hnjzsyjyj/article/details/139369904
val[idx]:存储编号为 idx 的边的值
e[idx]:存储编号为 idx 的结点的值
ne[idx]:存储编号为 idx 的结点指向的结点的编号
h[a]:存储头结点 a 指向的结点的编号
【算法代码】
#include <bits/stdc++.h>
using namespace std;const int maxn=1e5+5;
const int maxm=maxn<<1;
int e[maxm],ne[maxm],h[maxn],idx;
int din[maxn]; //in-degree
int tp[maxn]; //topological order
int n,m;void add(int a,int b) {e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}void topsort() {int hh=0, tt=-1;for(int i=1; i<=n; i++) {if(din[i]==0) tp[++tt]=i;}while(hh<=tt) {int t=tp[hh++];for(int i=h[t]; i!=-1; i=ne[i]) {int j=e[i];din[j]--;if(din[j]==0) tp[++tt]=j;}}if(tt==n-1) {for(int i=0; i<n; i++) {cout<<tp[i]<<" ";}} else cout<<"-1";
}int main() {cin>>n>>m;memset(h,-1,sizeof h);while(m--) {int a,b;cin>>a>>b;add(a,b);din[b]++;}topsort();return 0;
}/*
input:
3 4
1 2
2 1
2 3
3 1
output:
-1input:
5 5
1 3
1 5
2 1
3 4
3 5
output:
2 1 3 4 5
*/
【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/139369904
https://blog.csdn.net/hnjzsyjyj/article/details/116307687
https://www.lmlphp.com/user/18593/article/item/587756/
https://blog.csdn.net/weixin_44356316/article/details/104755034
https://www.acwing.com/solution/content/103954/
这篇关于AcWing 848:拓扑排序 ← 链式前向星存图的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!