拓扑排序
1.拓扑排序只对于有向无环图而言 (Directed Acyclic Graph简称DAG)
2.在一个有向无环图中,若a–>b–>c,则拓扑序列为 (a,b,c);也就是说如果一条边a—>b,那么在拓扑序列里a就在b前面;
知道了这两点,那么就可以来求拓扑序列了;
首先,我们知道在DAG中一定存在一个入度为0的点,那么这个点就是我们的起始点;根据这个点我们就可以通过bfs往后找,每找到一个相连点,就把这一条边删去,怎么删呢?
比如我们从a点开始,发现a与b相连,我们就要把a–>b这条边删去,就是b的入度减一,当发现一个点的入度为0时,就把这个点入队,并且用容器存下这个点;所得的容器里面的序列就是拓扑序列;
代码实现十分简单;
模板题:
给定一个n个点m条边的有向图,图中可能存在重边和自环。
请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出-1。
若一个由图中所有点构成的序列A满足:对于图中的每条边(x, y),x在A中都出现在y之前,则称A是该图的一个拓扑序列。
输入格式
第一行包含两个整数n和m
接下来m行,每行包含两个整数x和y,表示存在一条从点x到点y的有向边(x, y)。
输出格式
共一行,如果存在拓扑序列,则输出拓扑序列。否则输出-1。
代码:
#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define lson k<<1
#define rson k<<1|1
//ios::sync_with_stdio(false);
using namespace std;
const int N=100010;
const int M=200100;
const LL mod=1e9+7;
int n,m;
int cnt;
int head[N];
struct Node{
int to,nex;
}edge[N];
void add(int p,int q){
edge[cnt].to=q;
edge[cnt].nex=head[p];
head[p]=cnt++;
}
queue<int>qu;
vector<int>ve;
int s[N];//入度
void bfs(){
while(!qu.empty()){
int u=qu.front();
ve.push_back(u);
qu.pop();
for(int i=head[u];~i;i=edge[i].nex){
int v=edge[i].to;
s[v]--;
if(s[v]==0) qu.push(v);
}
}
}
int main(){
ios::sync_with_stdio(false);
memset(head,-1,sizeof(head));
cin>>n>>m;
for(int i=1;i<=m;i++){
int p,q;
cin>>p>>q;
s[q]++;
add(p,q);
}
for(int i=1;i<=n;i++){
if(s[i]==0) qu.push(i);
}
bfs();
if(ve.size()!=n){
cout<<-1<<endl;
return 0;
}
for(int i=0;i<ve.size();i++) cout<<ve[i]<<" ";
cout<<endl;
return 0;
}