【题意】给出一个有向图的边集,判断这个图是不是DAG
【解】用DFS,记录每个节点u的发现时间 u.d 和完成时间 u.f,一个有向图是DAG当且仅当DFS不产生后向边。如果u.d < v.d,且u.f > v.f 说明有一条v -> u的后向边。
#include<iostream>
#include<vector>
using namespace std;
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
init(numCourses, prerequisites);
int n = 0;
for (int i = 0; i < numCourses; i++)
{
if (!visited[i])
{
visited[i] = true;
pre[i] = n;
n++;
dfs(n, numCourses, i);
}
}
return find;
}
private:
vector<vector<int>> graph;
vector<bool> visited;
vector<int> pre; //discover time
vector<int> post; //finish time
bool find;
void init(int numCourses, vector<pair<int, int>>& edges)
{
find = true;
graph.resize(numCourses);
int n = edges.size();
for (int i = 0; i < n; i++)
graph[edges[i].first].push_back(edges[i].second);
visited.resize(numCourses);
for (int i = 0; i < numCourses; i++)
visited[i] = false;
pre.resize(numCourses);
for (int i = 0; i < numCourses; i++)
pre[i] = -1;
post.resize(numCourses);
for (int i = 0; i < numCourses; i++)
post[i] = -1;
}
void dfs(int& cur, int n, int start)
{
for (size_t i = 0; i < graph[start].size(); i++)
{
if (!visited[graph[start][i]])
{
visited[graph[start][i]] = true;
pre[graph[start][i]] = cur;
cur++;
dfs(cur, n, graph[start][i]);
}
else
{
if (pre[graph[start][i]] < pre[start] && post[graph[start][i]] == -1)
find = false;
}
}
post[start] = cur;
cur++;
}
};