LeetCode 802 Find Eventual Safe States (强连通分量,Tarjan)
2018-03-19 15:02
525 查看
LeetCode 802 Find Eventual Safe States (强连通分量,Tarjan)
Description
In a directed graph, we start at some node and every turn, walk along a directed edge of the graph. If we reach a node that is terminal (that is, it has no outgoing directed edges), we stop.Now, say our starting node is eventually safe if and only if we must eventually walk to a terminal node. More specifically, there exists a natural number
Kso that for any choice of where to walk, we must have stopped at a terminal node in less than
Ksteps.
Which nodes are eventually safe? Return them as an array in sorted order.
The directed graph has
Nnodes with labels
0, 1, ..., N-1, where
Nis the length of
graph. The graph is given in the following form:
graph[i]is a list of labels
jsuch that
(i, j)is a directed edge of the graph.
Example: Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]] Output: [2,4,5,6] Here is a diagram of the above graph.
解题思路
根据题意,Terminal Node指的是不属于任何一个大于1的强连通分量并且没有自环的点。可以先用Tarjan算法求出所有不是Ternimal Node的点,然后对于每个点深搜,如果这个点能走向一个不是Ternimal Node的点,那这个点就“不安全”,反之安全。
代码
class Solution { public: void tarjan(vector<vector<int>> &graph, vector<vector<int>> &SCCs, stack<int> &stk, int x, int &idx, int DFN[], int LOW[], int VST[]) { // 从第x个点开始 DFN[x] = LOW[x] = ++idx; // 新进点的初始化 stk.push(x); // 进栈 VST[x] = 1; //表示在栈里 for (auto &node : graph[x]) { if (!DFN[node]) { // 如果没访问过 tarjan(graph, SCCs, stk, node, idx, DFN, LOW, VST); // 往下进行延伸,开始递归 LOW[x] = min(LOW[x], LOW[node]); // 更新 LOW } else if (VST[node]) { // 如果访问过,并且还在栈里 LOW[x] = min(LOW[x], DFN[node]); // 更新 LOW } } if (LOW[x] == DFN[x]) { // 发现x是整个强连通分量子树里的最小根 vector<int> stronglyConnectedComponent; int top; do { top = stk.top(); stronglyConnectedComponent.emplace_back(top); cout << top << ' '; stk.pop(); VST[top] = 0; } while (x != top); SCCs.emplace_back(stronglyConnectedComponent); cout << endl; } } vector<vector<int>> Tarjan(vector<vector<int>> &graph) { int idx = 0; stack<int> stk; auto size = graph.size(); int DFN[size], LOW[size], VST[size]; // 每个点的时间戳,0表示没有被访问过 每个点的最小子树的根 每个点是否在栈中 fill_n(DFN, size, 0); fill_n(LOW, size, 0); fill_n(VST, size, 0); vector<vector<int>> stronglyConnectedComponents; for (int i = 0; i < size; ++i) { if (!DFN[i]) { // 如果这个点没有被访问过 tarjan(graph, stronglyConnectedComponents, stk, i, idx, DFN, LOW, VST); } } return stronglyConnectedComponents; } void dfs(int x, vector<vector<int>> &graph, vector<int> &isSafe) { if(isSafe[x]!=0) return; isSafe[x] = 1; for (auto &ConnectedNode:graph[x]) { if (isSafe[ConnectedNode] == 2) { isSafe[x] = 2; return; } else if (isSafe[ConnectedNode] == 0) { dfs(ConnectedNode, graph, isSafe); if (isSafe[ConnectedNode] == 2) isSafe[x] = 2; } } } vector<int> eventualSafeNodes(vector<vector<int>> &graph) { auto size = graph.size(); vector<int> ans; vector<int> isSafe(size, 0); // 每个点是否安全,0代表未访问,1代表安全,2代表不安全 unordered_set<int> Points; // 所有的点都: 属于一个大小大于1的强连通分量中或者有自环 vector<vector<int>> SCCs = Tarjan(graph); // 获得所有的强连通分量 for (auto &SCC:SCCs) { if (SCC.size() > 1) // 这个强连通分量的大小大于1 for (auto &Point:SCC) { Points.insert(Point); isSafe[Point] = 2; // 不安全 } else for (auto &connectedPoint:graph[SCC[0]]) { if (connectedPoint == SCC[0]) { // 这个点有自环,不是题中描述的Terminal Node Points.insert(SCC[0]); isSafe[SCC[0]] = 2; // 不安全 continue; } } } for (int i = 0; i < size; ++i) { if (!isSafe[i]) { // 如果未访问过 dfs(i, graph, isSafe); // 深搜来确认这个点是否能走向一个强连通分量 } if (isSafe[i] == 1) { // 这个点安全 ans.emplace_back(i); } } return ans; } };
相关文章推荐
- leetcode802——Find Eventual Safe States
- [LeetCode] Find Eventual Safe States 找到最终的安全状态
- 802. Find Eventual Safe States
- [HDU2767]Proving Equivalences(Tarjan缩点+强连通分量)
- POJ 2762 强连通分量中存在单相连通边 【tarjan+toposort+缩点】.cpp
- LeetCode Find Peak Element
- POJ1236 Network of Schools【Tarjan】【强连通分量】
- LeetCode 448 Find All Numbers Disappeared in an Array
- [LeetCode]Find Minimum in Rotated Sorted Array II
- [LeetCode]Find All Numbers Disappeared in an Array(Java)
- 上白泽慧音(tarjan求强连通分量)
- Codeforces Round #244 (Div. 2) 427C Checkposts (强连通分量 tarjan模板)
- [LeetCode153]Find Minimum in Rotated Sorted Array
- [Leetcode] Find the Difference
- LeetCode 162 Find Peak Element
- [LeetCode162]Find Peak Element
- Leetcode: Find Peak Element
- LeetCode 436. Find Right Interval 题解(C++)
- leetcode Find Minimum in Rotated Sorted Array
- leetcode oj java Find Minimum in Rotated Sorted Array