/**
* @author liaojiamin
* @Date:Created in 16:29 2021/1/8
*/
public class GraphDepthFirstSearch {
//递归调用深度优先搜索实现
public void depthFirst(Vertex v){
v.setKnow(true);
for (Vertex vertex : v.getVertexList()) {
if(!vertex.isKnow()){
depthFirst(vertex);
}
}
}
}
如上图,如A 顶点数据(1/1),第一个数据表示Num(v),是先序遍历的顺序字段,图中树结构的先序遍历顺序是A,B,C,D,E,F,G。
第二个数据表示的是Low(v),所有顶点的Low(v)开始都等于Num(v),顶点A的low(v)是本身,
D的邻接节点中存在A节点,所以按以上规则Low(v)是最小的Num(v)所以取A 顶点的Num(v)
同理C节点邻接节点是D也是1,B节点邻接C也是1
E节点邻接F,F背向边到D,所以F,E,都是D节点的Num(v) = 4.
G没有背向节点,所以是本身 7
我们依据以上Low定义可以指定Low(v)是满足如下规则:
以上规则中第一条是不选取边,本身就是最小,第二条规则是不选取树的边而是选取一条背向边,第三种规则我们可以用递归调用简单的描述,由于我们需要对v的所有子节点算出Low值后才能得到最小Low(v),因此这是一个后续遍历。对于任意的(v,w),只要检查Num(v)和Num(w)就知道他是树的一条边还是一条背向边,(因为按树生成算法背向边总数从大的 num值 到小的num值)。因此Low(v)容易计算,我们只需要扫描v的邻接节点,然后记住最小值。时间复杂度在O(E+V)。
接着我们需要做的就是利用以上信息找到所有割点。
/**
* @author liaojiamin
* @Date:Created in 16:29 2021/1/8
*/
public class GraphDepthFirstSearch {
//假设图基本数据结构已经被读入邻接表中
private static final List<Vertex_v1> vertices = new ArrayList<>();
private Integer counter = 0;
/**
* 深度优先递归模板
* */
public void depthFirst(Vertex_v1 v){
v.setKnow(true);
for (Vertex_v1 vertex : v.getVertexList()) {
if(!vertex.isKnow()){
depthFirst(vertex);
}
}
}
/**
* 深度优先递归赋值nnum
* */
public void assignNum(Vertex_v1 v){
v.setNum(counter++);
v.setKnow(true);
for (Vertex_v1 vertex_v1 : v.getVertexList()) {
if(!vertex_v1.isKnow()){
vertex_v1.setPath(v);
assignNum(vertex_v1);
}
}
}
/**
* 同样的算法,深度优先对Low赋值
* */
public void assignLow(Vertex_v1 v){
v.setLow(v.getNum());
for (Vertex_v1 w : v.getVertexList()) {
//w > v 标识w是v的子节点
if(w.getNum() > v.getNum()){
assignLow(w);
//割点规则
if(w.getLow() > v.getNum()){
System.out.println(v.getNum() + " is an articulation point");
}
v.setLow(Math.min(v.getLow(), w.getLow()));
}else if(v.getPath().compareTo(w) != 0){
//此处不能写成: v.setLow(Math.min(v.getLow(), w.getLow()));因为此种情况是在最后二次访问边路径的时候得到,可能w的Low已经被修改成更小的值
v.setLow(Math.min(v.getLow(), w.getNum()));
}
}
}
/**
* 还是用深度优先搜索,结合以上两种规则,值进行一次遍历得到
* */
public void findArt(Vertex_v1 v){
v.setKnow(true);
v.setNum(counter++);
v.setLow(v.getNum());
for (Vertex_v1 w : v.getVertexList()) {
if(!w.isKnow()){
w.setPath(v);
findArt(w);
if(w.getLow() >= v.getNum()){
System.out.println(v.getNum() + " is an articulation point");
}
v.setLow(Math.min(v.getLow(), w.getLow()));
}else if(v.getPath().compareTo(w) != 0){
//此处不能写成: v.setLow(Math.min(v.getLow(), w.getLow()));因为此种情况是在最后二次范文边路径的时候得到,可能w的Low已经被修改成更小的值
v.setLow(Math.min(v.getLow(), w.getNum()));
}
}
}
}
上一篇:数据结构与算法–图论-最短路径算法应用
下一篇:数据结构与算法–贪婪算法:模拟调度问题