I use visited[] to record each node's state, where 0 means not visited, 1 means being visited and 2 means visited.

```
class Solution {
private:
bool dfs(int node, vector<unordered_set<int>> adj, vector<int>& visited) {
if (visited[node] == 2) {
return true;
}
if (visited[node] == 1) {
return false;
}
visited[node] = 1;
for (auto neighbor : adj[node]) {
if (!dfs(neighbor, adj, visited)) {
return false;
}
}
visited[node] = 2;
return true;
}
vector<unordered_set<int>> makeGraph(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<unordered_set<int>> adj(numCourses);
for (auto prerequisite : prerequisites) {
adj[prerequisite.second].insert(prerequisite.first);
}
return adj;
}
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<unordered_set<int>> adj = makeGraph(numCourses, prerequisites);
vector<int> visited(numCourses, 0);
for (int i = 0; i < numCourses; i++) {
if (!dfs(i, adj, visited)) {
return false;
}
}
return true;
}
};
```