宽度优先搜索,常用在最短路径这种题目中
1. 拓扑序列
给定一个包含 n 个节点的有向图 G,我们给出它的节点编号的一种排列,如果满足: 对于图 G 中的任意一条有向边 (u, v),u 在排列中都出现在 v 的前面,则是一种拓扑序列
有相图的拓扑序列:记录每个点的入度和出度,如果是正确的拓扑序列=>就不会存在环=>有相无环图至少存在一个入度为0的点
1.1 207. 课程表
题意也就是说验证这个序列中无环,(a,b)表示b之前必须完成a,那就让a->b
步骤:
- 建图并记录所有节点的入度。
- 将所有入度为0的节点加入队列。
- 取出队首的元素now,将其加入拓扑序列。
- 访问所有now的邻接点nxt,将nxt的入度减1,当减到0后,将nxt加入队列。
- 重复步骤3、4,直到队列为空。
- 如果拓扑序列个数等于节点数,代表该有向图无环,且存在拓扑序。
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> graph(numCourses);
vector<int> indegree(numCourses);
//建图
for(auto edge : prerequisites)
{
graph[edge[0]].push_back(edge[1]);
indegree[edge[1]] ++;
}
queue<int> q;
int num = 0;
//加入当前入度为0的点
for(int i = 0 ; i < numCourses;i ++)
{
if(indegree[i] == 0) q.push(i);
}
//取出入度为0的点,消去这个点指出去的每条边(也就是指向的点的入度),因为这个边对答案没有影响
while(!q.empty())
{
auto now = q.front();
q.pop();
num ++;
for(int next_pos :graph[now])
{
indegree[next_pos] --;
if(indegree[next_pos] == 0) q.push(next_pos);
}
}
return num == numCourses;
}
};