拓扑排序
很简单的一个东西,之前学由于完全没有图论基础知识没学懂
是什么
在图论中,拓扑排序
(
T
o
p
o
l
o
g
i
c
a
l
S
o
r
t
i
n
g
)
(Topological Sorting)
(TopologicalSorting)是一个有向无环图
(
D
A
G
,
D
i
r
e
c
t
e
d
A
c
y
c
l
i
c
G
r
a
p
h
)
(DAG, Directed Acyclic Graph)
(DAG,DirectedAcyclicGraph)的所有顶点的线性序列。
且该序列必须满足下面两个条件:
1.每个顶点出现且只出现一次。
2.若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面。
如何求图的拓扑排序
简单的BFS即可
- 先将图中所有入度为0的点入队(入度为0必定在前面)
- 依次拓展所有入度为0的点所连的顶点,将其入度-1
- 若扩展过程中被扩展的点入度减为0,入队即可
拓展完所有顶点,则找到一个拓扑排序
通常,一个有向无环图可以有一个或多个拓扑排序序列。
代码实现
#include<bits/stdc++.h>
//#pragma GCC optimize(2)
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
using namespace std;
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);cout.tie(0)
#define ll long long
#define ull unsigned long long
#define PII pair<int,int>
#define pb push_back
#define all(a) a+1,a+n+1
#define ALL(a) a.begin(),a.end()
#define debug(a) cout <<#a << "=" << a << endl;
const int INF = 0x3f3f3f3f;
const ll LINF = 1ll<<60;
const int mod=1e9+7;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
inline void write(int x){if(x<0) putchar('-'),x=-x;if(x>9) write(x/10);putchar(x%10+'0');}
//du入度,dv出度,vis标记是否走过
int n,m,du[100010],dv[100010],vis[100010];
std::vector<int> mp[100010];//存图
queue<int> q;//BFS队列
std::vector<int> ans;//保存答案
int main(){
cin>>n>>m;
int u,v;
rep(i,1,m) {
cin>>u>>v,mp[u].pb(v);
du[v]++,dv[u]++;
}
rep(i,1,n){
if(du[i]==0)//拓展所有入度为0的点
q.push(i),ans.pb(i),vis[i]=1;
}
while(q.size()){//BFS
int now=q.front();
q.pop();
for(auto it:mp[now]){
if(du[it]!=0){
du[it]--;
if(du[it]==0){//若当前点入度被减少为0,入队并保存答案
ans.pb(it);
q.push(it);
}
}
}
}
rep(i,1,n) {//查看是否有没有被拓展到的点
if(du[i]!=0){
cout<<-1<<endl;
return 0;
}
}
for(auto it:ans){
cout<<it<<" ";
}
return 0;
}