赞
踩
题目大意:从一个结点出发,最终能走到一个没有出边的点,那么这个起始点称为安全点。给出有向图的邻接表,问图里哪些点是安全点。
分析:
方法一:dfs。这道题的意思就是看从哪些点出发没有能回到原点的环存在。给图中的结点上色,初始化为0号色(color[i]=0表示没访问过该结点),dfs时遍历到的结点染1号色(表示访问过该节点),遍历邻接表判断如果无环则该节点染2号色(表示安全无环)。
方法二:拓扑排序。安全节点=无出边。将图中的所有边反向(注意题中给的graph是邻接表,不是leetcode210中给出的边集合),此时安全节点=无入边的点(入度为0),与安全节点相连的点也是安全节点,所以将入度为0的点和它的出边删掉后,剩下的入度为0的点也是安全节点,这一过程就是拓扑排序的过程。
代码:
方法一:dfs
- class Solution {
- public:
- vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
- int n = graph.size();
- vector<int> color(n);
- vector<int> ans;
- for(int i = 0;i < n;i++){ //dfs每个结点判断是否有环
- if(dfs(i,color,graph))
- ans.push_back(i);
- }
- return ans;
- }
- bool dfs(int i,vector<int>& color,vector<vector<int>>& graph){
- if(color[i]) return color[i] == 2; //如果染色是安全状态2就返回true
- color[i] = 1; //初始染1号色,相当于标记这次dfs过程中访问过它,但它的状态不确定是否安全
- for(auto nei : graph[i]){
- // 邻接节点不安全 || 邻接节点的邻接节点不安全
- if(color[nei] == 1 || !dfs(nei,color,graph))
- return false;
- }
- color[i] = 2;
- return true;
- }
- };
方法二:拓扑排序
- class Solution {
- public:
- vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
- vector<vector<int>> pre(graph.size()); //记录每个节点的后续结点
- vector<int> degree(graph.size(),0); //记录每个结点的入度
- for (int i = 0;i < graph.size();i++) {
- for(int j = 0;j < graph[i].size();j++){
- degree[i]++;
- pre[graph[i][j]].push_back(i);
- }
- }
- queue<int> q; //队列维护入度为0的结点
- for(int i = 0;i < graph.size();i++){
- if(degree[i] == 0) q.push(i);
- }
- vector<int> schedule;
- while(!q.empty()){
- int now = q.front();
- q.pop();
- schedule.push_back(now);
- for(int i = 0;i < pre[now].size();i++){
- degree[pre[now][i]]--;
- if(degree[pre[now][i]] == 0) q.push(pre[now][i]);
- }
- }
- sort(schedule.begin(),schedule.end());
- return schedule;
- }
- };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。