拓扑序列
概念
拓扑序列遵循一个规则,在遍历图的时候必须保证一条有向边的起点排在终点的前面
举一个例子
提供的有向边为:1 -> 2 | 2 -> 3 | 1 -> 3
满足条件
而1 - > 2 | 2 -> 3 | 3 -> 1
就不满足条件
如何实现拓扑序列?
- 找到所有入度为0的点,将其放入到队列中
- 将这些点从队列中弹出,并且将这些点所指向的终点的点入度减1
- 最后判断这些点是否入度为0,如果为0重新放入到队列中,循环这三种情况
Step1:找到入度为0的点
for(int i = 1;i <= n;i++) { if(!in(i)) q.push(i); }
|
Step2:使该点指向的终点入度减1
while(q.size()) { int fr = q.front(); q.pop(); for(int i = h[fr];~i;i = ne[i]) { int j = ne[i]; in[j]--; } }
|
Step3:检查入度为0,重新放入队列
while(q.size()) { int fr = q.front(); q.pop(); for(int i = h[fr];~i;i = ne[i]) { int j = ne[i]; in[j]--; if(!in[j]) q.push(j); } }
|
完整代码
#include <bits/stdc++.h> using namespace std; const int N = 100010; int e[N],h[N],ne[N],idx; queue<int> q; int d[N],top[N];int n,m,cnt; void add(int a,int b) { e[idx] = b; ne[idx] = h[a]; h[a] = idx++; }
bool topsort() { for(int i = 1;i <= n;i++) { if(!d[i]) q.push(i); }
while(q.size()) { int t = q.front(); top[cnt++] = t; q.pop(); for(int i = h[t];i != -1;i = ne[i]) { int j = e[i]; d[j]--; if(d[j] == 0) { q.push(j); } } }
return cnt == n; }
int main(){ memset(h,-1,sizeof(h)); int a,b; cin >> n >> m; while(m--) { cin >> a >> b; d[b]++; add(a,b); } if(!topsort()) { cout << -1 << endl; }else { for(int i = 0;i < n;i++) { cout << top[i] << " "; } cout << endl; } return 0; }
|