【Q】
【WHAT】
拓扑序列满足每条边(x,y),x在序列中都在y前面。
一个有向图,图中入度为0的点可以作为源点(不会有边在它前面),每次删去队头和连接它的所有边。一直进行上面处理,如果所有点都能被删掉,则这个图可以进行拓扑排序。
【HIGHLIGHT】
一个有向无环图,一定至少存在一个入度不为零的点。
无向图没有拓扑序列。
【Analysis】
1.首先记录每个点及其入 度
2.将入度为零的点全部放入队列
3.删除从队列出来的点的所有出边,则另一边点的入 度--
4.如果所有点都进队列,则可以组成拓扑序列,依次输出队列中的元素;否则,-1 ^-^
【CODE】
#include <bits/stdc++.h>
using namespace std;
const int N=1000010;
int e[N],ne[N],h[N],idx;
int d[N],q[N];
int n,m;
void add(int x,int y){
e[idx]=y;
ne[idx]=h[x];
h[x]=idx++;
}//邻接表
int topsort(){
int hh=0,tt=-1;//首尾指针
for(int i=1;i<=n;i++){
if(!d[i]) q[++tt]=i;//如果当前点入度为零 加入队列
}
while(hh<=tt){//对于不能确定的点
int t=q[hh++];//获取队头
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
if(--d[j]==0) q[++tt]=j;//入度--直到为零 加入队列
}
}
return tt==n-1;//结束
}
int main(){
scanf("%d%d",&n,&m);
memset(h,-1,sizeof(h));
for(int i=0;i<m;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
d[y]++;
}
if(!topsort()) cout<<"-1";
else{
for(int i=0;i<n;i++){
printf("%d ",q[i]);
}
}
return 0;
}