拓扑排序是一种用于有向无环图(DAG)的节点排序算法。它可以用来解决一些依赖关系的问题,例如任务调度、编译顺序等。
拓扑排序的基本思想是通过不断地选择入度为0的节点,并移除其出边,直到所有节点都被选中为止。具体的步骤如下:
1. 统计每个节点的入度。
2. 将所有入度为0的节点加入到一个队列中。
3. 循环执行以下步骤:
- 从队列中取出一个节点,将其输出。
- 更新与该节点相邻节点的入度,如果入度减为0,则将其加入队列中。
4. 如果所有节点都被输出,则排序成功;否则,图中存在环,排序失败。
拓扑排序算法的时间复杂度为O(V+E),其中V为节点数,E为边数。在实际应用中,拓扑排序可以使用深度优先搜索(DFS)或广度优先搜索(BFS)来实现。
需要注意的是,拓扑排序算法只适用于有向无环图,如果图中存在环,则无法进行拓扑排序。
那么我们可以用拓扑排序来判断图是否有环
1.用桟或队列来储存入度为0的点;
2.初始化桟或队列,循环节点压入所有入度为0的点;
3.取桟或队列的节点x,删去x的路径(其实就是删掉x链接节点的入度),当入度减少时,循环节点,压入所有入度为0的点,在去重节点的同时计数;
4.直到桟或队列的大小为0,若计数的大小等于节点数,则为无环,反之,有环;
#include <bits/stdc++.h>
#define ll long long
#define endl "\n"
#define KUI ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;
const int con = 1e7 + 5;
int n, m, k;
int rd[con];
int main()
{
KUI;
cin >> n;
int a1, a2;
vector<int> v[n + 1];
for (int i = 1; i <= n; i++)
{
cin >> a1 >> a2;
v[a1].push_back(a2);
rd[a2]++;
}
queue<int> q;
for (int i = 1; i <= n; i++)
{
if (rd[i] == 0)
{
q.push(i);
}
}
int jishu = 0;
while (q.size() > 0)
{
int ans = q.front();
q.pop();
jishu++;
for (auto &x : v[ans])
{
rd[x]--;
if (rd[x] == 0)
{
q.push(x);
}
}
}
if (jishu == n)
{
cout << "有环" << endl;
}
else
{
cout << "无环" << endl;
}
return 0;
}