问题:在有向图 ( 只有1 个开始节点, 1 个结束节点) 中判断任意两个节点是否为相同层次,不考虑环的情况,
A,B为相同层次可以理解为经过A的数据流必然经过B,经过B的数据流也必然经过了A
例
a>b
a>c
b>d
c>d
其中 b ,c 节点为并行节点,都完成之后到达 d 节点,其中a , d为相同层次 ,a,b;b,d;b,c 都不是相同层次
另外一个例子
a>b
a>c
b>c
c>d
b>d
其中 a,d 为相同层次,其他都不是
/** * 算法核心思想: * a的数据流必经过b的深刻含义为,a的数据流无论从哪条路走都必须经过b,这就要求a的相邻节点也具有该特性; * 同理将有向图反向,b的数据流也必经过a */ public class SameLevel { //n为节点个数,e为有向边个数 private static int n,e; //有向图正向临接表 private static Map<Character,LinkedList<Character>> adjacencyMap = new HashMap<Character,LinkedList<Character>>(); //有向图反向临接表 private static Map<Character,LinkedList<Character>> adjacencyReverseMap = new HashMap<Character,LinkedList<Character>>(); /* * 创建正向与反向临接表 * 输入格式参考如下: * 4 4 //输入节点个数与有向边数 * a b c d //输入各个节点 * a b // 以下四行有输入的有向边 * a c * b d * c d * a d //输入需要判断层次的任意两个节点 */ public static boolean createGraph(Scanner sc){ n = sc.nextInt(); e = sc.nextInt(); if(n == 0 || e == 0) return false; for(int i=0;i<n;i++){ char c = sc.next().toCharArray()[0]; adjacencyMap.put(c,new LinkedList<Character>()); adjacencyReverseMap.put(c,new LinkedList<Character>()); } for(int i=0;i<e;i++){ char c = sc.next().toCharArray()[0],d = sc.next().toCharArray()[0]; LinkedList<Character> list = adjacencyMap.get(c), rlist = adjacencyReverseMap.get(d); list.addFirst(d); rlist.addFirst(c); } return true; } /* * 判断a是否从任意路径可达b */ public static boolean DFSTraverseAtoB(char a ,char b , boolean []visited){ if(a == b) return true; boolean ret = true; LinkedList<Character> adjacentList = adjacencyMap.get(a); for(char c : adjacentList){ Arrays.fill(visited,false); if(!DFS(c,b,visited) || !DFSTraverseAtoB(c,b,visited)){ ret = false; break; } } return ret; } /* * 深度优先遍历算法 */ public static boolean DFS(char a , char b , boolean[] visited){ if(a == b){ return true; } visited[a] = true; LinkedList<Character> adjacentList = adjacencyMap.get(a); for(char c : adjacentList){ if(!visited[c]){ if(DFS(c,b,visited)){ return true; } } } return false; } /* * 判断两个节点是否是同一层次 */ public static boolean isSameLevel(char a ,char b){ boolean ret = false,ret1 = false; if(!adjacencyMap.containsKey(a) || !adjacencyMap.containsKey(b)){ throw new RuntimeException("Node Doesn't exist!"); } boolean[] visited = new boolean[256]; ret = DFSTraverseAtoB(a ,b ,visited); adjacencyMap = adjacencyReverseMap; //有向图反向再判断一次 ret1 = DFSTraverseAtoB(b,a ,visited); return ret && ret1; } public static void main(String[]args){ Scanner sc = new Scanner(System.in); boolean created = createGraph(sc); if(!created){ throw new RuntimeException("Create graph failed!"); } Character a = sc.next().toCharArray()[0],b = sc.next().toCharArray()[0]; boolean ret = isSameLevel(a,b); System.out.println(ret); } }
由于上述代码不够灵活,效率不高,且不好测试,重构后的代码如下:
public class SameLevel { //n为节点个数,e为有向边个数 private static int n,e; //有向图正向临接表 private static Map<Character,LinkedList<Character>> adjacencyMap = new HashMap<Character,LinkedList<Character>>(); //有向图反向临接表 private static Map<Character,LinkedList<Character>> adjacencyReverseMap = new HashMap<Character,LinkedList<Character>>(); //填充正向与反向临接表 private static void fullMap(Map<Character,LinkedList<Character>> map,Character a,Character b){ if(!map.containsKey(a)){ map.put(a,new LinkedList<Character>()); } map.get(a).add(b); if(!map.containsKey(b)){ map.put(b,new LinkedList<Character>()); } } /* * 根据输入的map创建图 */ public static boolean createGraph(Set<Edge<Character>> set){ if(set == null || set.size() == 0) return false; for(Edge<Character> edge : set){ Character key = edge.getStart(),value = edge.getEnd(); fullMap(adjacencyMap,key,value); fullMap(adjacencyReverseMap,value,key); } return true; } /* * 判断a是否从任意路径可达b */ public static boolean DFSTraverseAtoB(char a ,char b){ if(a == b) return true; boolean ret = false; LinkedList<Character> adjacentList = adjacencyMap.get(a); for(char c : adjacentList){ if(!DFSTraverseAtoB(c,b)){ return false; } ret = true; } return ret; } /* * 判断两个节点是否是同一层次 */ public static boolean isSameLevel(char a ,char b, Set<Edge<Character>> set){ if(set == null || set.size() == 0) return false; boolean ret = false,ret1 = false,created = createGraph(set); if(!created || !adjacencyMap.containsKey(a) || !adjacencyMap.containsKey(b)){ throw new RuntimeException("Error!"); } ret = DFSTraverseAtoB(a ,b); adjacencyMap = adjacencyReverseMap; //有向图反向再判断一次 ret1 = DFSTraverseAtoB(b,a); return ret && ret1; } /* * */ public static void main(String[]args){ Set<Edge<Character>> set = new HashSet<Edge<Character>>(); set.add(new Edge<Character>('a','b')); set.add(new Edge<Character>('b','c')); set.add(new Edge<Character>('b','d')); set.add(new Edge<Character>('d','e')); set.add(new Edge<Character>('c','d')); System.out.println(isSameLevel('a','d',set)); } /* * 定义有向图的边对象 * @start 为边的起点 * @end 为边的终点 */ static class Edge<T>{ private T start; private T end; public T getStart() { return start; } public void setStart(T start) { this.start = start; } public T getEnd() { return end; } public void setEnd(T end) { this.end = end; } public Edge(T start,T end){ this.start = start; this.end = end; } } }
https://gist.github.com/narutolby/8348153#file-gistfile1-java
相关推荐
**定义:** 有向无环图(Directed Acyclic Graph, DAG)是一种特殊的有向图,其中没有任何一条路径能够形成一个环路。换句话说,在一个DAG中,不存在任何起点和终点相同的有向路径。 **应用场景:** - **任务调度**...
这些方法涵盖了有向图的基本操作和常见问题的解决,通过理解和实现这些方法,可以深入理解有向图的性质和应用。 三、邻接链表的优缺点 优点: 1. 空间效率高,尤其对于稀疏图。 2. 添加和删除顶点或边的时间复杂度...
这个问题涉及到有向图(Directed Graph)的概念,其中的边具有方向性,即从一个节点指向另一个节点。 **有向图**是由顶点(Vertex)和有方向的边(Arc)构成的。每个边都有一个起点和一个终点,从起点指向终点。在...
本题主要涉及有向图、无向图、邻接矩阵、邻接表、强连通分量、最短路径算法(Dijkstra、Floyd)、最小生成树算法(Prim、Kruskal)、拓扑排序、完全二叉树和AOE网等概念。 1. 有向图G=(V,E)的定义:V是顶点集合,E...
在有向图中,如果从每个节点都可以到达其他所有节点,我们称之为强连通图;如果仅存在单向路径使得所有节点可达,那么是弱连通图。 程序的核心算法可能包含以下部分: 1. **深度优先搜索(DFS)**:DFS 是一种遍历...
总之,无向图的DFS和BFS遍历是图论中的基础操作,它们在许多问题中起到关键作用,如路径查找、拓扑排序和寻找连通分量等。理解和掌握这些概念以及如何在实际编程中实现它们,对于提升在算法和数据结构方面的技能非常...
在铁路信号系统中,车站联锁的层次结构是确保列车安全、高效运行的关键技术之一。本文将详细解析铁路信号系统车站联锁的层次结构,并针对各个层级的功能与组成进行深入探讨。 ### 一、车站联锁层次结构概述 车站...
- 回路检测:可以使用深度优先搜索或广度优先搜索来判断有向图是否存在环。 4. 空间复杂度 - 邻接矩阵存储图的空间复杂度为 O(n^2),而邻接表通常更节省空间,为 O(n+e)。 - 无向图的邻接表中,边表的结点数为 2...
18. 判断一个有向图是否存在回路,可以使用深度优先遍历。如果在遍历过程中发现回到已访问过的节点,那么图中存在回路。 综上所述,本题涉及到的知识点包括:图的基本概念,无向图和有向图的特点,完全图的概念,图...
【层次分析法(AHP)】AHP通过构建层次结构模型,将复杂问题分解为多个易于比较的因素,通过专家或决策者的两两对比判断,形成判断矩阵,进而量化这些主观判断,提高决策的合理性。这种方法强调逻辑性、系统性和实用...
- 判断有向图是否有环,拓扑排序是一种有效的方法。如果在拓扑排序过程中遇到环,就会导致无法继续排序。问题(15)的答案是B。 以上知识点涵盖了图的基本性质、遍历算法以及相关应用,这些都是图论和算法课程中的...
通过对有丝分裂各阶段图像的辨识与分析,学生能够更加直观地理解细胞周期和遗传规律,进而对生命科学有更深层次的认知。教师通过图像的引导和讲解,能够帮助学生形成严谨的观察习惯和科学的思维方式,为将来的学习和...
1. **邻接矩阵**:对于无向图或有向图来说,邻接矩阵是一种常见的存储结构。它用一个二维数组表示图中顶点之间的关系,对于无向图而言,该矩阵是对称的。如果顶点\( v_i \)到顶点\( v_j \)之间存在一条边,则邻接...
- 连通有向图至少需要 \(n\) 条边来确保图的连通性。 - 正确答案为 **B**:\(n\)。 5. **完全有向图的边数**: - 完全有向图中的每一对不同的顶点间都有一条方向确定的边。 - 完全有向图的边数为 \(n(n-1)\)。 ...
层次聚类的基本思想是从单个样本开始,逐渐合并最相似的样本或群组,直到所有样本都属于同一个群组,或者满足预设的终止条件。这个过程可以用两种方式表示:凝聚型自底向上和分裂型自顶向下。 1. 凝聚型层次聚类:...
在有向图中,一个顶点通过有向边指向另一个顶点,我们说前者邻接至后者,后者邻接自前者。 图结构与其他数据结构如线性结构(如数组、链表)和树结构有所不同。线性结构中,元素间的关系是一对一的前后关系;树结构...
这些题目主要涵盖了图的基本概念,包括图的类型(有向图和无向图)、图的存储结构(邻接矩阵和邻接表)、图的遍历(深度优先和广度优先)、最小生成树算法(Prim 和 Kruskal)、图的性质(如度数、连通性、拓扑排序...
层次分析法(AHP,Analytic Hierarchy Process)是一种用于决策分析的方法,它结合了定量与定性的分析,尤其适用于处理复杂多目标的问题。这种方法由托马斯·塞韦林·萨蒂(Thomas L. Saaty)提出,主要用于在无法...
在寻找正方形对面的过程中,有一个重要的技能需要学生掌握,即在同一行或同一列中隔开一个正方形的两个正方形是相对面。这个规律对于理解展开图和折叠正方体至关重要。通过观察和分析,学生可以更清楚地认识到展开图...