Week 7
Nonrecursive depth-first search
问题
Implement depth-first search in an undirected graph without using recursion.
思路
使用循环而非递归实现DFS
设计
使用显式的stack完成DFS,实际上感觉和BFS的实现逻辑是一样的
Diameter and center of a tree
问题
Given a connected graph with no cycles
- Diameter: design a linear-time algorithm to find the longest simple path in the graph.
- Center: design a linear-time algorithm to find a vertex such that its maximum distance from any other vertex is minimized.
思路
找到一棵树的直径(最长路径)和中心(最小最长路径)
下面的证明来自https://blog.csdn.net/pi9nc/article/details/12394117
主要是利用了反证法:
假设 s-t这条路径为树的直径,或者称为树上的最长路
现有结论,从任意一点u出发搜到的最远的点一定是s、t中的一点,然后在从这个最远点开始搜,就可以搜到另一个最长路的端点,即用两遍广搜就可以找出树的最长路
证明:
设u为s-t路径上的一点,结论显然成立,否则设搜到的最远点为T则
dis(u,T) >dis(u,s) 且 dis(u,T)>dis(u,t) 则最长路不是s-t了,与假设矛盾
设u不为s-t路径上的点
首先明确,假如u走到了s-t路径上的一点,那么接下来的路径肯定都在s-t上了,而且终点为s或t,在1中已经证明过了
所以现在又有两种情况了:
- u走到了s-t路径上的某点,假设为X,最后肯定走到某个端点,假设是t ,则路径总长度为dis(u,X)+dis(X,t)
- u走到最远点的路径u-T与s-t无交点,则dis(u-T) >dis(u,X)+dis(X,t);显然,如果这个式子成立,则dis(u,T)+dis(s,X)+dis(u,X)>dis(s,X)+dis(X,t)=dis(s,t)最长路不是s-t矛盾
设计
- 直径:两遍BFS,随便找一个点v,然后第一遍BFS找到最长最短路距离的点w,然后第二遍BFS找到最长最短距离的点x,那么x和w之间就是直径(最长路)
- 中心:直径上的点(中间的点就好了)
Euler cycle
问题
An Euler cycle in a graph is a cycle (not necessarily simple) that uses every edge in the graph exactly one.
- Show that a connected graph has an Euler cycle if and only if every vertex has even degree.
- Design a linear-time algorithm to determine whether a graph has an Euler cycle, and if so, find one.
思路
问题一,因为我们经过途中的每一条边一次且仅一次,那么对于一个具备欧拉环路的图,每次我们通过一条边到达一个顶点,那么我们一定要从另外一条边离开这个点(因为要找到环路),因此每个点必然是偶数度
设计
先看图的度数,DFS遍历就好了,遍历一条边就反选掉,最后一定能遍历完,否则就不是有欧拉环的图
Shortest directed cycle.
问题
Given a digraph G G G, design an efficient algorithm to find a directed cycle with the minimum number of edges (or report that the graph is acyclic). The running time of your algorithm should be at most proportional to V ( E + V ) V(E + V) V(E+V) and use space proportional to E + V E + V E+V, where V V V is the number of vertices and E E E is the number of edges.
思路
这个时间复杂度暗示性太强了……
设计
对每一个点,运行一次BFS,找到能够回到初始点的最少边数
Hamiltonian path in a DAG.
问题
Given a directed acyclic graph, design a linear-time algorithm to determine whether it has a Hamiltonian path (a simple path that visits every vertex), and if so, find one.
思路
DAG的话,拓扑排序既是线性的,又是对每一个点遍历一次
设计
完成拓扑排序
Reachable vertex.
问题
- DAG: Design a linear-time algorithm to determine whether a DAG has a vertex that is reachable from every other vertex, and if so, find one.
- Digraph: Design a linear-time algorithm to determine whether a digraph has a vertex that is reachable from every other vertex, and if so, find one.
思路(非原创)
对DAG,需要注意,一旦一个顶点有到达其他顶点的边,那么他就一定不能被这个顶点可达
对含环的有向图,在求强连通分量时有一个思路可以将其转换成DAG,同时对于强连通分量,任一点可以被其他点可达
设计
- 对DAG,计算每一个点的出度,取唯一的出度为0的(注意,如果有超过一个出度为0的点,那么这两点之间必不可达)点
- 求强连通分量,然后检查核心DAG