///定义:
/*
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,
是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边
(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称
为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,
由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
*/
///扩展:
/*
(1)实现步骤
1) 选择一个入度为0的顶点并输出之;
2) 从网中删除此顶点及所有出边。
(2)时间复杂度
O(E+V)
*/
/*
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,
是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边
(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称
为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,
由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
*/
///代码:
/*
**name:拓扑排序
**function:输出字典序最小的拓扑序列
**输入参数:拓扑关系图
**输出参数:字典序最小的拓扑序列
*/
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200000+7;
struct node{
int to,nex;
}eage[maxn<<1];
int head[maxn],deg[maxn],cnt;
int ans[maxn];
priority_queue<int>q;///大顶优先队列
void ADD(int u,int v){
eage[cnt].to = v;
eage[cnt].nex = head[u];
head[u] = cnt++;
}
void Toposort(int n){
while(!q.empty())q.pop();
for(int i = 1;i<=n;i++){
if(!deg[i])q.push(i);
}
int top = 0;
while(!q.empty()){
int u = q.top();
q.pop();
ans[top++] = u;
for(int i = head[u];i!=-1;i = eage[i].nex){
int v = eage[i].to;
deg[v]--;
if(!deg[v])q.push(v);
}
}
for(int i = top-1;i>=0;i--){///逆向输出
printf("%d%c",ans[i],i==0?'\n':' ');
}
}
/*
**输出按字典序最小的拓扑排序
*/
int main(){
int n,m,x,y;///n个点,m条边
while(~scanf("%d%d",&n,&m)){
memset(head,-1,sizeof(head));
memset(deg,0,sizeof(deg));
cnt = 0;
for(int i =0;i<m;i++){
scanf("%d%d",&x,&y);
ADD(y,x);///反向建边
deg[x]++;///入度+1
}
Toposort(n);
}
return 0;
}
///扩展:
/*
(1)实现步骤
1) 选择一个入度为0的顶点并输出之;
2) 从网中删除此顶点及所有出边。
(2)时间复杂度
O(E+V)
*/