题目
思路
这里只给一些疑惑上的解答:
- 为什么不删除边?
- 这里是等效的,因为入度数减少1,且起点从队列弹出了不会再进入
- 为什么可以直接从q里找序列,不会出现点重复进入吗?
- 点进入的条件是入度为0,此时没有边的终点是该点了,这个点不会再出现(当然出现了了入度要变成-1,嘻嘻),所以不会再次进入队列
- 为什么初始化一次要进入多个0入度点
- 过程中变成入度为0,是这个点最后一次出现的状态,之后这个点不会再出现了
- 最开始为0,这个点就根本不会被遍历到,只能靠开始压入
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10, M = N;
int h[N], e[M], ne[M], idx;
int q[N], hh = 0, tt = -1;
int ind[N], cnt;
int n, m;
void add(int a, int b) // 添加一条边a->b
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
void topo()
{
for(int i = 1; i <= n; i++)
if(ind[i] == 0) q[++tt] = i;
while(hh <= tt)
{
int u = q[hh++]; cnt++;
for(int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
ind[j]--;
if(ind[j] == 0) q[++tt] = j;
}
}
if(cnt == n)
{
for(int i = 0; i < n; i++)
cout << q[i] << ' ';
}
else cout << -1;
}
int main()
{
cin >> n >> m;
memset(h, -1, sizeof h);
for(int i = 1; i <= m; i++)
{
int a, b;
cin >> a >> b;
ind[b]++;
add(a, b);
}
topo();
}