有向图的拓扑排序
给定一个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≤1e5
拓扑排序:判断有向图中是否有重边或者自环。
`解题思路:首先遍历一遍图,找出入度为0的点,把它push到队列中去,然后把这个点延伸出来的边都去除掉,(du[指向的点]–),最后判断是否还有入度不为0的点即可,如果还有的话,输出-1;
Code:
#include<iostream>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1e5+7;
int n,m;
int du[maxn];
vector<int> ve[maxn],ans;
queue<int> q;
void topo(){
while(!q.empty()){
int p=q.front();
q.pop();
ans.push_back(p);
for(auto it:ve[p]){
du[it]--;
if(du[it]==0) q.push(it);
}
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
ve[u].push_back(v);
du[v]++;
}
for(int i=1;i<=n;i++){
if(du[i]==0) {
q.push(i);
}
}
topo();
if(ans.size()!=n) cout<<-1<<endl;
else{
for(auto it:ans) cout<<it<<" ";
}
puts("");
}