有向图判环

有这样一道编程面试题,给一个有向图的邻接矩阵,判别它是否有环。

题目麻烦在给的邻接矩阵是以 ‘字符输入流’ 的形式给出的,所以将其处理成数字形式的是首先要做的工作。

得到邻接矩阵之后,进行拓扑排序即可。假如能完成拓扑排序那就无环,如果不能,那就是有环。

样例输入:

[[0, 1, 0], [0, 0, 1], [1, 0, 0]]

[[0, 0, 0, 1, 0], [1, 0, 0, 0, 0], [0, 0, 0, 1, 1], [0, 0, 0, 0, 0], [0, 1, 0, 0, 0]]

输出:(1代表有环,0代表无环)

1

0

 

 1 #include <bits/stdc++.h> 
 2 using namespace std; 
 3 
 4 int main(int argc, char const *argv[]){
 5     string str;
 6     while(getline(cin, str) ){        
 7         vector<int> data;
 8         for(int i=0; i<str.size(); i++){
 9             if(str[i]=='0' || str[i]=='1'){
10                 data.push_back(str[i]-'0');
11             }            
12         }
13                 
14         int n = sqrt( data.size() );                      //n是节点个数
15         vector<vector<int> > graph(n,vector<int>(n,0));   //邻接矩阵 
16         
17         for(int i=0; i<n; i++){
18             for(int j=0; j<n; j++){ 
19                 graph[i][j] = data[n*i+j];
20             } 
21         }
22         
23         vector<int> visited(n,0);    //n是节点个数,从上面处理后得到
24         vector<int> indegree(n,0);   //各个节点的入度
25         for(int i=0;i<n;i++){
26             for(int j=0;j<n;j++){
27                 if(graph[i][j]==1){
28                     indegree[j]++;
29                 }                
30             }
31         } 
32         queue<int> q;
33         for(int i=0;i<n;i++){
34             if(indegree[i]==0) 
35                 q.push(i);
36         }
37         
38         int now;
39         while(!q.empty()){
40             now = q.front();
41             q.pop();
42             visited[now] = 1;
43             for(int i=0;i<n;i++){
44                 if(!visited[i] && graph[now][i]==1){
45                     indegree[i]--;
46                     if(indegree[i]==0) q.push(i); 
47                 }
48             }
49         }
50         
51         bool sign = 0;
52         for(int i=0; i<n; i++){
53             if(!visited[i]){
54                 sign = 1;
55                 break;
56             }            
57         }
58         
59         cout<<sign<<endl;
60     } 
61         
62     return 0;
63 }

 

转载于:https://www.cnblogs.com/liugl7/p/11272614.html

### 无向图的算法实现 在无向图中断是否存在可以通过多种方法来完成,常见的方法包括深度优先搜索(DFS)、广度优先搜索(BFS),以及并查集等。下面详细介绍基于 DFS 的解决方案。 #### 基于深度优先搜索 (DFS) 的检测 通过深度优先遍历可以有效地检测无向图中的。核心思想是在访问节点的过程中记录当前路径上的父节点,并检查是否有边连接到已经访问过的节点且该节点不是其直接父节点的情况。如果发现这样的情况,则说明存在。 具体实现逻辑如下: - 使用布尔数组 `visited` 来标记已访问的节点。 - 对每一个未被访问的节点执行递归调用。 - 如果遇到一个已经被访问过但并非当前节点的父亲节点,则表明找到了一条回路。 下面是 C++ 中的一个简单实现: ```cpp #include <iostream> #include <vector> using namespace std; class Graph { int V; // Number of vertices vector<vector<int>> adj; public: Graph(int V); void addEdge(int v, int w); bool isCyclicUtil(int v, vector<bool>& visited, int parent); bool isCyclic(); }; Graph::Graph(int V) { this->V = V; adj.resize(V); } void Graph::addEdge(int v, int w) { adj[v].push_back(w); adj[w].push_back(v); } bool Graph::isCyclicUtil(int v, vector<bool> &visited, int parent) { visited[v] = true; for(auto i : adj[v]) { if(!visited[i]){ if(isCyclicUtil(i, visited, v)) return true; } else if(parent != i){ return true; } } return false; } bool Graph::isCyclic() { vector<bool> visited(V, false); for(int u=0;u<V;u++) { if (!visited[u]) if (isCyclicUtil(u, visited, -1)) return true; } return false; } ``` 上述代码定义了一个类 `Graph` 并实现了函数 `isCyclic()` 和辅助函数 `isCyclicUtil()` 。当调用 `isCyclic()` 方法时会返回布尔值指示图中是否存在[^1]。 #### Java 版本的实现 对于同样的问题,在 Java 编程语言下也可以采用类似的策略解决。这里给出一段完整的测试程序作为参考: ```java import java.util.*; public class CycleDetection { private Map<Integer, List<Integer>> adjacencyList = new HashMap<>(); private Set<Integer> visitedNodes = new HashSet<>(); public void addEdge(int source, int destination) { adjacencyList.putIfAbsent(source, new ArrayList<>()); adjacencyList.get(source).add(destination); adjacencyList.putIfAbsent(destination, new ArrayList<>()); adjacencyList.get(destination).add(source); } public boolean detectCycle() { for(Integer node : adjacencyList.keySet()) { if( !visitedNodes.contains(node)){ if(dfsDetectCycle(node,-1)) return true; } } return false; } private boolean dfsDetectCycle(int currentNode,int parentNode){ visitedNodes.add(currentNode); for(Integer neighbor : adjacencyList.getOrDefault(currentNode,new ArrayList<>())){ if(!visitedNodes.contains(neighbor)){ if(dfsDetectCycle(neighbor,currentNode)) return true; }else{ if(neighbor!=parentNode) return true; } } return false; } public static void main(String[] args)throws Exception{ String filename="D:\\Desktop\\graph5.txt"; CycleDetection cd=new CycleDetection(); Scanner sc=new Scanner(new File(filename)); while(sc.hasNext()){ int src=sc.nextInt(),dest=sc.nextInt(); cd.addEdge(src, dest); } sc.close(); System.out.println("是否存在:"+cd.detectCycle()); } } ``` 此段代码展示了如何读取文件构建邻接表形式存储的图结构,并利用递归方式查找其中可能存在的任何循关系[^4]。 ### 总结 无论是使用哪种编程语言或者数据结构表示法,关键是理解基本原理——即借助栈特性模拟探索过程的同时维护必要的状态信息以便识别重复访问情形下的异常状况。这种方法能够满足时间复杂度 O(N+M)[^2]的要求,适用于大多数实际应用场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值