判断有向图是否有环

在图论中,如果一个有向图从任意顶点出发无法经过若干条边回到该点,则这个图是一个有向无环图(Directed Acyclic Graph,DAG). 对于一个n个节点的有向图(节点编号从0到n-1),请判断其是否为有向无环图.
 
图的节点数和边数均不多于100000.
 
请为下面的Solution类实现解决上述问题的isDAG函数,函数参数中n为图的节点数,edges是边集,edges[i]表示第i条边从edges[i].first指向edge[i].second. 如果是有向无环图返回true,否则返回false.
 
class Solution {
public:
       bool isDAG(int n, vector<pair<int, int>>& edges) {
          
    }
};
 
例1:
n = 3,edges = {(0, 1), (0, 2)},函数应返回true.
 
例2:
n = 2,edges = {(0, 1), (1, 0)},函数应返回false.

主要思想:拓扑排序,先把边集转化为邻接表,同时计算各个点的入度。维持一个栈来保存已经排好序的点。一开始先把图中所有入度为0的点先入栈,然后开始循环。取出栈顶元素,想象在图中删除它,然后删除以它为源点的边,同时维持别的点的入度。如果出现入度为0的点,入栈。最后栈为空时,退出循环。复杂度O(V+E)

// Problem#: 20620
// Submission#: 5138131
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
class Solution {
public:
    bool isDAG(int n, vector<pair<int, int> >& edges) {
        vector<vector<int> > matrix(n);
        int degree[100000];
        for(int i = 0; i < n; i++)degree[i] = 0;
        for(int i = 0; i < edges.size(); i++){
            matrix[edges[i].first].push_back(edges[i].second);
            degree[edges[i].second]++;
        }  
        int count = 0;
        stack<int> q;
        for(int i = 0; i < n; i++)
            if(degree[i] == 0){
                count++;
                q.push(i);
            }
        while(!q.empty()){
            int j = q.top();
            q.pop();
            for(int i = 0; i < matrix[j].size(); i++){
                degree[matrix[j][i]]--;
                if(degree[matrix[j][i]] == 0){
                    q.push(matrix[j][i]);
                    count++;
                }
            }
        }
        return count == n? true: false;
    }
};                                 


然后是DFS的做法,一开始的想法是取一个点做DFS,如果遍历到的点已经在路径上,则有环。但如果图存在不联通的两个孤岛,DFS就会中断。这时还需要加一层循环,这样会超时(我写的会超时)。

下面用递归的办法做DFS,给所有顶点都判断一遍。函数check的作用是判断顶点v开始的DFS是否有回路,若有,返回true。这个略快一点。

class Solution {
public:
	int visit[100000]; 
	
    bool isDAG(int n, vector<pair<int, int> >& edges) {
    	vector<vector<int> > matrix(n);
    	for(int i = 0; i < edges.size(); i++){
    		matrix[edges[i].first].push_back(edges[i].second);
		}
    	for(int i = 0; i < n; i++)visit[i] = 0;
		for(int i = 0; i < n; i++)
			if(check(i, matrix))return false;
		return true;
	}
	bool check(int v, vector<vector<int> >& matrix)
	{
		if(visit[v])return true;
		visit[v] = true;
		for(int i = 0; i < matrix[v].size(); i++){
			if(check(matrix[v][i], matrix))return true;
		}
		visit[v] = false;
		return false;
	}
};

这是不用递归版本的DFS证明是不是有环图的方法:

class Solution {
public:
    bool isDAG(int n, vector<pair<int, int> >& edges) {
    	//转换邻接矩阵 
    	vector<vector<int> > matrix(n);
    	for(int i = 0; i < edges.size(); i++){
    		matrix[edges[i].first].push_back(edges[i].second);
		}
		stack<int> q;
		int visit[100000];
		for(int i = 0; i < n; i++){
			visit[i] = -1;
		}
		
		for(int i = 0; i < n; i++){//防止出现不连通图的一层循环 
			q.push(i);
			visit[i] = 1;
			while(!q.empty()){
				int d = q.top(), i;
				for(i = 0; i < matrix[d].size(); i++){
					if(visit[matrix[d][i]] == -1){
						q.push(matrix[d][i]);
						visit[matrix[d][i]] = 1;
						break;
					}
					if(visit[matrix[d][i]] == 1)return false;
				}
				if(i == matrix[d].size()){
					q.pop(); visit[d] = 0;
				}
			}
		}
		
		return true;
    }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值