You could try searching for topological sorting of directed graphs.
As far as I know, if a directed graph has a cycle, it cannot be topologically sorted, so the topological sorting algorithm can be used to detect whether there is a cycle.
The following is a possible implementation, where adj is an array in the form of an adjacency linked list.
adj[i] is a vector that represents all neighbor nodes of node i.
s is the current node
recSt is a stack.
bool DFSRec(vector<vector<int>> adj, int s, vector<bool> visited, vector<bool>  recSt)
{
  visited[s] = true;
  recSt[s] = true;
  for (int u : adj[s]) {
    if (visited[u] == false && DFSRec(adj, u, visited, recSt) == true)
      return true;
    else if (recSt[u] == true)
      return true;
  }
  recSt[s] = false;
  return false;
}
bool DFS(vector<vector<int>> adj, int V) {
  vector<bool> visited(V, false);
  vector<bool> recSt(V, false);
  for (int i = 0; i < V; i++)
    if (visited[i] == false)
      if (DFSRec(adj, i, visited, recSt) == true)
        return true;
  return false;
}
and there is another one
vector<int>kahns(vector<vector<int>> g) {
  int n = g.size();
  vector<int> inDegree(n);
  for (auto edges : g)
    for (int to : edges)
      inDegree[to]++;
  queue<int> q;  //q里包含的永远是入度为0的node
  for (int i = 0; i < n; i++)
    if (inDegree[i] == 0)
      q.push(i);
  int index = 0;
  vector<int> order(n);
  while (!q.empty()) {
    int at = q.front(); q.pop();
    order[index++] = at;
    for (int to : g[at]) {
      inDegree[to]--;
      if (inDegree[to] == 0)
        q.push(to);
    }
  }
  if (index != n)return {}; //has cycle
  return order;
}
Here is a link that might be useful
here is some video that may related
https://www.youtube.com/watch?v=eL-KzMXSXXI
https://www.youtube.com/watch?v=cIBFEhD77b4