图
有向图的拓扑排序(用来判环)
定义
将有向图中的顶点以线性方式进行排序。即对于任何连接自顶点u到顶点v的有向边uv,在最后的排序结果中,顶点u总是在顶点v的前面。
存在条件
如果存在环,那么就不可能满足u->v时u总是在v的前面了。所以必须是有向五环图(DAG)才能拓扑排序。
是否唯一
如果该DAG任意两个顶点都有确定的关系,拓扑排序就是唯一的。如果有这么一个唯一的拓扑排序,容易知道这样的顺序恰好能够遍历全图且每个顶点只经过一次,我们把这样的路径叫做哈密顿路径。
Kahn算法
维护一个入度为0的集合S,每次从S中取出一个点放入存储答案的L数组,检查该点出发的所有边及连接的点,从图中移除这些边,如果连接的点在删除这条边以后入度变为0,将它加入到集合S中。
如此循环,直到集合S中没有点为止,检查图上还有没有边存在,如果有就存在环,如果没有L数组中存储的就是拓扑排序的结果。
集合S可以用栈实现。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
int in[100100],n,m;
priority_queue<int> s;
vector<vector<int> > edge(100010);
vector<int> ans;
void Kahn(){
while(!s.empty()){
int cur=s.top();
s.pop(); ans.push_back(cur);
printf("%d ",cur);
vector<int> :: iterator it;
for(it=edge[cur].begin();it!=edge[cur].end();it++){
in[*it]--;
if(!in[*it]){
s.push(*it);
}
}
}
}
int main(){
memset(in,0,sizeof(in));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
edge[x].push_back(y);
in[y]++;
}
for(int i=1;i<=m;i++){
if(in[i]==0) {
s.push(i);
//printf("%d ",i);
}
}
Kahn();
return