拓扑排序学习笔记

Deadly 提交于 2019-11-30 01:40:29

拓扑排序

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;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!