6.2.1 二分图
如果可以用两种颜色对图中的节点进行着色,并且保证相邻的节点颜色不同,那么这个图就是二分图。
-
判断二分图: https://leetcode-cn.com/problems/is-graph-bipartite/
class Solution { private: // constexpr表达式是指值不会改变并且在编译过程就能得到计算结果的表达式。 // 声明为constexpr的变量一定是一个const变量,而且必须用常量表达式初始化 static constexpr int UNCOLORED = 0; static constexpr int RED = 1; static constexpr int GREEN = 2; vector<int> color; bool valid; public: void dfs(int node, int c, const vector<vector<int>>& graph) { color[node] = c; int cNei = (c == RED ? GREEN : RED); for (int neighbor: graph[node]) { if (color[neighbor] == UNCOLORED) { dfs(neighbor, cNei, graph); if (!valid) { return; } } else if (color[neighbor] != cNei) { valid = false; return; } } } bool isBipartite(vector<vector<int>>& graph) { int n = graph.size(); valid = true; color.assign(n, UNCOLORED); for (int i = 0; i < n && valid; ++i) { if (color[i] == UNCOLORED) { dfs(i, RED, graph); } } return valid; } };
6.2.2 拓扑排序
常用于在具有先序关系的任务规划中。
x
- 课程表: https://leetcode-cn.com/problems/course-schedule/
class Solution { private: vector<vector<int>> edges; vector<int> visited; bool valid = true; public: void dfs(int u) { visited[u] = 1; for (int v: edges[u]) { if (visited[v] == 0) { dfs(v); if (!valid) { return; } } else if (visited[v] == 1) { valid = false; return; } } visited[u] = 2; } bool canFinish(int numCourses, vector<vector<int>>& prerequisites) { edges.resize(numCourses); visited.resize(numCourses); for (const auto& info: prerequisites) { edges[info[1]].push_back(info[0]); } for (int i = 0; i < numCourses && valid; ++i) { if (!visited[i]) { dfs(i); } } return valid; } };
6.2.3 并查集
并查集可以动态地连通两个点,并且可以非常快速地判断两个点是否连通。
-
冗余连接: https://leetcode-cn.com/problems/redundant-connection/
class Solution { public: int Find(vector<int>& parent, int index) { if (parent[index] != index) { parent[index] = Find(parent, parent[index]); } return parent[index]; } void Union(vector<int>& parent, int index1, int index2) { parent[Find(parent, index1)] = Find(parent, index2); } vector<int> findRedundantConnection(vector<vector<int>>& edges) { int n = edges.size(); vector<int> parent(n + 1); for (int i = 1; i <= n; ++i) { parent[i] = i; } for (auto& edge: edges) { int node1 = edge[0], node2 = edge[1]; if (Find(parent, node1) != Find(parent, node2)) { Union(parent, node1, node2); } else { return edge; } } return vector<int>{}; } };