1.拓扑排序
为了我们的代码可以跑的更快,我们这里使用数组模拟的单链表来构造:存储信息的邻接表
int h[N],e[N],ne[N],idx;
int d[N],值为点i的入度
h[N]的值为头节点所指向的位置;
e[idx]的值为一条路径上到达的点,比如存储一条边a->c,e[idx]的值就是c
en[idx]的值为当前点指向哪一个点
idx的值为当前我们加入的是第几个点
将一条边的信息加入邻接表的操作如下
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
信息存储结束后我们进行拓扑排序
1.我们要把每一个头节点的值初始化
memset(h,-1,sizeof(h));
2.我们把每一个入度为0的点找出来,加入到队列q中
int hh=0,tt=-1;
for(int i=1;i<=n;i++) if(!d[i]) q[++tt]=i;
3.将入度为0的点加入到队列q中意味着,以该点为基础的边被拆掉了,那么这条边对应的另外一个点的入度自然减小了一个
这时候我们判断这个点入度是不是0,是0就将他加入到队列中;
while(hh<=tt)
{
int j=q[++hh];
for(int i=h[j];i!=-1;i=ne[i])
{
int k=e[i];
if(--d[k]==0) q[++tt]=k;
}
}
完整代码如下
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int N=1e6;
int n,m;
int h[N],e[N],ne[N],idx;
int q[N], d[N];
void add(int a,int b)
{
e[idx]=b; ne[idx]=h[a]; h[a]=idx++;
}
bool 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()
{
mem(h,-1);
cin>>n>>m;
int a,b;
while(m--)
{
cin>>a>>b;
add(a,b);
d[b]++;
}
if(!topsort()) cout<<"-1"<<endl;
else
{
for(int i=0;i<n;i++) cout<<q[i]<<' ';
cout<<endl;
}
return 0;
}