题目:
拓扑排序: 某个节点不能指向它前面的点,否则就会形成环,就不是拓扑序列。有向无环图一定是拓扑序列。 大致思路:将所有入度为0的点入队,然后遍历某个入队为0的点的所有出边,删除它的所有出边, 所连的另个一端点入度-1, 如果该点入度变为0, 就将其入队。当队列为空时,要么所有点都入队了,要么就是存在环,所遍历到的某个点的入度不为0(形成了环),因此可以通过入队的点数来判断是否为拓扑序列。由于起始入度为0的点的入队先后顺序不确定,因此拓扑序列不唯一。这些点入队的顺序所形成的序列刚好就是拓扑序列
代码:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
int h[N], e[N], ne[N], idx;
int d[N], q[N];
int n, m;
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] == 0)
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()
{
memset(h, -1, sizeof h);
cin >> n >> m;
while(m -- )
{
int a, b;
cin >> a >> b;
add(a, b);
d[b] ++;
}
if(topsort())
{
for(int i = 0; i < n; i ++ )
cout << q[i] << ' ';
}
else cout << -1 << endl;
return 0;
}