Mryqu's Notes


  • 首页

  • 搜索
close

[算法] 学习无向图

时间: 2014-03-21   |   分类: Algorithm.DataStruct     |   阅读: 246 字 ~2分钟

本文是学习http://algs4.cs.princeton.edu/41graph/的吐槽和体会。

一点吐槽

一开始对GraphClient.java中numberOfSelfLoops函数进行count/2不解,翻回Graph.java,看看addEdge函数才明白,合着对自循环连接,adj里面加两次。这么干有什么好处么?!!

再后来看Cycle.java,对hasParallelEdges函数又不解,仔细想想Graph.java不但接受addEdge(1,23)和addEdge(23, 1),对执行多次addEdge(1,23)也不拒绝。一个无向图这么弄,对么?算不算检查不严格呀?!!

理解Cycle.java

示例代码:

public static void main(String[] args) {
  Graph G = new Graph(4);
  G.addEdge(0, 1);
  G.addEdge(1, 2);
  G.addEdge(1, 3);
  G.addEdge(2, 3);    
  Cycle finder = new Cycle(G);
  if (finder.hasCycle()) {
    for (int v : finder.cycle()) {
      StdOut.print(v + " ");
    }
    StdOut.println();
  }
  else {
    StdOut.println("Graph is acyclic");
  }
}

dfs搜索:

|上一节点u|当前节点v|下一节点w|注解 |—– |-1|0|1|节点1没有标注,嵌套dfs |0|1|3|节点3没有标注,嵌套dfs |1|3|2|节点2没有标注,嵌套dfs |3|2|1|节点1已标注,发现cycle,创建栈,依次:

  • (在for循环中)push 2
  • (在for循环中)push 3
  • push 1
  • push 2说白了就是当发现下一节点w已经标注,那就返回去找w到v的路径,然后凑上w和v,就是一个环路。

理解Bipartite.java

二分图又称作二部图、两偶图,是图论中的一种特殊模型。设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(iin A,j in B),则称图G为一个二分图。

简而言之,就是顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属于这两个互不相交的子集。

Bipartite.java的控制流与CC.java差不多。设定图中节点为红黑两种颜色,为了使相邻节点不同颜色,dfs时下一节点颜色为当前节点反色。当遇到环路时,如果环路节点数为奇数个(下一节点已标注且颜色与当前节点相同),则该图非二分图。

理解Bridge.java

桥(割边cut-edge)是一个边,当其被删除时连通组件个数会增多。同样道理,一个边仅没有被任何环路包含时才是一个桥。

示例代码:

public static void main(String[] args) {
        Graph G = new Graph(5);
        G.addEdge(0, 1);
        G.addEdge(1, 3);
        G.addEdge(1, 2);
        G.addEdge(2, 3);
        G.addEdge(3, 4);        
  StdOut.println(G);

  Bridge bridge = new Bridge(G);
  StdOut.println("Edge connected components = " + bridge.components());
}

dfs搜索: [算法] 学习无向图 dfs过程中,发现环路后整个环路上所有节点low值降成环路中第一个处理节点的pre值。下一个节点pre值与最终low值一致的话,当前节点和下一节点之间的边为桥。

注:对于连接组件的第一个处理节点,Cycle.java中dfs函数的u参数为-1,而Bridge.java中的dfs函数的u参数为当前节点v。

输出日志:

5 vertices, 5 edges 
0: 1 
1: 2 3 0 
2: 3 1 
3: 4 2 1 
4: 3 

3-4 is a bridge
0-1 is a bridge
Edge connected components = 3

理解Biconnected.java

关节点(articulation vertex,又称割点cutvertex)是一个节点,当其被删除时连通组件个数会增多。当没有关节点时,图为双连通图。

示例代码:

public static void main(String[] args) {
  Graph G = new Graph(5);
  G.addEdge(0, 1);
  G.addEdge(1, 3);
  G.addEdge(1, 2);
  G.addEdge(2, 3);
  G.addEdge(3, 4);
  StdOut.println(G);

  Biconnected bic = new Biconnected(G);

  // print out articulation points
  StdOut.println();
  StdOut.println("Articulation points");
  StdOut.println("-------------------");
  for (int v = 0; v < G.V(); v++)
    if (bic.isArticulation(v)) StdOut.println(v);
}

dfs搜索: [算法] 学习无向图 dfs过程中,发现环路后整个环路上所有节点low值降成环路中第一个处理节点的pre值。当前节点pre值小于等于下一节点最终low值,且当前节点非连接组件第一个处理节点时,当前节点即为割点。

注:对于连接组件的第一个处理节点,Cycle.java中dfs函数的u参数为-1,而Biconnected.java中的dfs函数的u参数为当前节点v。

输出日志:

5 vertices, 5 edges 
0: 1 
1: 2 3 0 
2: 3 1 
3: 4 2 1 
4: 3 


Articulation points
-------------------
1
3

理解EulerianCycle.java

通过图(无向图或有向图)中所有边且每边仅通过一次通路称为欧拉通路(Eulerian trail,Eulerianpath),相应的回路称为欧拉回路( Eulerian circuit,Euleriancycle)。具有欧拉回路的图称为欧拉图(EulerGraph),具有欧拉通路而无欧拉回路的图称为半欧拉图(Semi-Eulerian)。

|图论起源于18世纪,1736年瑞士数学家欧拉(Euler)发表了图论的第一篇论文“哥尼斯堡七桥问题”。在当时的哥尼斯堡城有一条横贯全市的普雷格尔河,河中的两个岛与两岸用七座桥连结起来。当时那里的居民热衷于一个难题:有游人怎样不重复地走遍七桥,最后回到出发点。为了解决这个问题,欧拉用A,B,C,D4个字母代替陆地,作为4个顶点,将联结两块陆地的桥用相应的线段表示,于是哥尼斯堡七桥问题就变成了图中,是否存在经过每条边一次且仅一次,经过所有的顶点的回路问题了。欧拉在论文中指出,这样的回路是不存在的。|[算法] 学习无向图

无向连通图G含有欧拉通路,当且仅当G有零个或两个奇数度的结点;无向连通图G是欧拉图,当且仅当G不含奇数度结点(G的所有结点度数为偶数)。

EulerianCycle.java判断当某个节点度为奇数,则不是欧拉图。否则任选一点度大于零的点做起点,记录路径是否走过,一点接一点直到当前点对相邻点没有未走路径为止。最后判断所走路径上节点数是否为图所有节点个数+1,如不等则非欧拉图。(感觉即使是欧拉图靠贪婪查找也不确保能获得正确路径。)

平面图

一个图是片面的,指其画在平面时边没有交叉。Hopcroft-Tarjan算法基于dfs能在线性时间内判断图是否为平面的。

汉密尔顿图

通过图(无向图或有向图)中所有节点且每节点仅通过一次的通路称为哈密顿通路(Hamiltonian path,Traceablepath),相应的回路称作汉密尔顿回路(Hamiltonian cycle)。

美国图论数学家奥勒在1960年给出了一个图是哈密尔顿图的充分条件:对于顶点个数大于2的图,如果图中任意两点度的和大于或等于顶点总数,那这个图一定是哈密尔顿图。寻找哈密顿路径是一个典型的NP-完全问题。

标题:[算法] 学习无向图
作者:mryqu
声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!

#algorithm# #graph# #cycle# #bipartite# #eulerian#
玩一下LineNumberReader
GitHub fork操作
  • 文章目录
  • 站点概览

Programmer & Architect

662 日志
27 分类
1472 标签
GitHub Twitter FB Page
    • 一点吐槽
    • 理解Cycle.java
    • 理解Bipartite.java
    • 理解Bridge.java
    • 理解Biconnected.java
    • 理解EulerianCycle.java
    • 平面图
    • 汉密尔顿图
© 2009 - 2023 Mryqu's Notes
Powered by - Hugo v0.120.4
Theme by - NexT
0%