`
frank-liu
  • 浏览: 1682584 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Girth of graph

 
阅读更多

问题描述

    在前面的一篇文章中我们讲述过怎么去检测一个图形中间是否有环。对于很多图来说,它们确实存在环,而且可能存在的环长度也各不相同。这里,就引入了一个概念,叫做girth。对于一个不存在环的图来说,它的girth为无穷大,而对于一个存在环的图来说,它的girth为最小的环长度。

    我们以下面几个图为例:

    这个图正好形成了一个环,所以它的girth值就是环的长度,为6。而下图中它的girth值则为无穷大:

 

    所以,这里的问题就是给定一个图,求出它的girth值。

 

问题分析

    从前面的问题描述可以看到,要求一个图的girth,需要考虑几个点。一个是看它是否存在有环,如果没有环,则girth值为无穷大。另外一个就是如果它确实存在有环,就要求每个环的长度,然后取得最小环的长度。

    对于第一个部分来说,问题还好说,前面的文章里已经阐述过如果处理的办法了。通过一个标记数组,每次访问一个节点所关联的所有节点时,如果碰到一个以前曾经访问过的节点,除去那个按照遍历方法到达当前节点的前置节点,那么说明存在有一个环。

 

寻找回路

    现在对于第二个问题,就是前面的方法找到了存在回路,该如何把这个回路的所有元素以及它的长度给找出来呢?结合前面判断图中间存在环问题的解法,我们来这么考虑。

    首先,判断图中间是否存在环,是通过一种遍历图的方法。在不管是通过dfs还是bfs遍历的时候。每个节点对应数组boolean[] marked中的一个。当节点被访问过,则对应位置被设置为true。这样后面再次遍历到的时候,如果发现这个位置已经被设置为true,这说明了什么呢?前面的遍历都是基于某一个单点来开始的,所以当我们将某个节点设置为true的时候,表示从一个给定的单点到这个节点是连通的。而第二次碰到这个原来被访问的节点时候呢?说明从第二次碰到这个节点的点到源节点也是连通的。这不就至少说明了,从源节点,到这个两次被碰到的节点以及第二次碰到这个节点前的这个点构成了一个环吗?以下图为例:

 

     假设我们第一次访问到目的节点t的时候,是通过节点s1,因为这个时候是以s为源节点开始遍历的。不管怎么说,肯定可以确定的就是节点s到s1到t是连通的。当我们通过第二次访问到节点t时,通过的是节点sk,如下图:

    基于前面同样的道理,sk可以连接到t,s也肯定可以连接到sk。这个时候,从s到s1到t再到sk,加上s到sk的这一段,不就正好构成了一个回路了么?

 

比对所有环路

    现在,按照这种思路确实可以找到回路。我们从一个单独的点出发,在图整个是连通的情况下,这一个点就完全遍历了整个图。按照前面的方法找到的回路,是不是就有最佳的呢?我们来看一个如下的具体图:

 

    假定我们从节点1开始作为源节点,它确实可以遍历所有节点。比如说当我们遍历到节点10的时候,我们会发现它被从6过来的节点访问过。另外,它也被从7过来的节点访问过。如果按照前面的思路来说,6和源节点1是连通的,7和1也是连通的。那么1到6,加上6到10,10到7,再加上7到1,这就构成了一个环。这个环结构如下:{1, 2, 6, 10, 7, 4, 3, 1} 。可是从直观的角度我们可以看到,这里最小的那个环应该是{6, 10, 7}这个。这说明了什么呢?我们前面检测环的这个过程,只是保证找到所有包含源节点在内的环,并不包含这些个不包含源节点的环。所以,光通过遍历一个节点来比对得出的环只是整个图中间存在环的一部分。按照原来的思路会遗漏一部分。所以,如果要找到所有的环进行比对的话,我们必须要通过所有的节点来做一遍前面的环检测,然后将最小的那个环返回回来。

 

实现

    有了前面这么些讨论,现在可以细化实现的代码了。我们这里一个个考虑过来。

1. 首先这里要通过所有的节点进行遍历,来查找环。那么,用哪种遍历方式呢?

    这里我们采用广度优先遍历的方法。

2. 如何判断节点是否被访问过?

    用一个boolean[] marked节点,长度和节点数一样,访问一次后对应的节点设置为true.

3. 如何保存遍历过的节点呢?

    用一个edgeTo[]节点,比如说通过节点u到节点v的时候,就将edgeTo[v] = u。这样我们根据一个节点的edgeTo[]节点就可以找到它前面的一个节点。这样一路倒推可以找到源节点。

4. 如何保存最小的环以及环所包含的节点呢?

    我们可以考虑用一个数字int来表示环的长度,并用一个集合,比如LinkedList或者ArrayList来保存这个环中间所有的节点。

    有了前面这些讨论,我们通过一个节点遍历得到通过该节点的最小环代码如下:

private void bfs(Graph g, int s) {
        Queue<Integer> q = new LinkedList<Integer>();
        for(int v = 0; v < g.v(); v++) distTo[v] = INFINITY;
        distTo[s] = 0;
        marked[s] = true;
        q.add(s);
        while(!q.isEmpty()) {
            int v = q.remove();
            for(int w : g.adj(v)) {
                if(!marked[w]) {
                    edgeTo[w] = v;
                    distTo[w] = distTo[v] + 1;
                    marked[w] = true;
                    q.enqueue(w);
                } else if(edgeTo[w] != v) {
                    updateGirth(w, v);
                }
            }
        }
    }

    这是在广度优先遍历算法的基础上做了一些修改。distTo[]数组保存的是从源节点到当前节点的距离,这样计算环长度的时候就更简单了,只要distTo[u] + distTo[v] + 1就是了。代码里关键的部分是updateGirth()方法。它的实现如下:

private void updateGirth(int w, int v) {
        if(distTo[w] + distTo[v] + 1 < girthSize) {
            girthSize = distTo[w] + distTo[v] + 1;
            girthPath.clear();
            for(Integer i : pathTo(w)) {
                girthPath.add(i);
            }
            for(int x = v; distTo[x] != 0; x = edgeTo[x]) {
                girthPath.add(x);
            }
        }
    }

     girthSize是表示环长度的值。最开始设置为最大整数值。所以前面要比较这个环的长度和girthSize,如果比这个girthSize小才有意义。这里用了两个循环,第一个部分是记录了从源节点到w节点的这一段路径。第二部分因为是要从v倒退到源节点,所以不用去遍历的取pathTo()方法里的元素。而pathTo()方法的实现如下:

public Iterable<Integer> pathTo(int v) {
        if(!hasPathTo(v)) return null;
        Stack<Integer> path = new Stack<Integer>();
        int x;
        for(x = v; distTo[x] != 0; x = edgeTo[x])
            path.push(x);
        return path;
    }

   详细的代码里还封装了包含当前源节点在内的最短环路径和路径长度。详细的代码实现可以见附件。

    附件里的代码实现了一个从某个节点开始去遍历得到的最小环。实际上,因为前面要得到整体的最小,所以还需要一个循环,构造出BreadthFirstPaths对象,然后取得其中最小的。这部分就没有详细写出来了,因为很简单,这里只是写一个大概:

public get minPath(Graph g) {
    int minSize = Integer.MAX_VALUE;
    for(int i : g.v()) {
        bfp = new BreadthFirstPaths(g, i); 
        if(bfp.getGirthSize() < minSize) {
            minSize = bfp.getGirthSize();
            minPath = bfp.getGirthPath();
        }
    }
    return minPath;
}

 

总结

     Girth这个词本身的意思是指一个东西的围长,相当于一个人的腰围或者一个桶的周长。只是结合它在图论里的定义,更多的像是木桶原理里指的那个短板。所以一时还不知道该用什么词来描述它好。这个问题相当于在找一个图中间存在环的问题基础上更进一步。找一个路径长度最小的环。我们这里通过遍历每个节点查找通过该节点的环,然后从中间筛选出最小的那个。实际上,在通过中间的一个或者若干个节点,保证可以覆盖整个图的时候,我们就可以得到一些中间节点访问过的信息,如果能够充分利用好这些信息,也许可以不用去通过所有节点来作遍历。不过目前只是一个想法,不知道是否可行。以后可以试试。

 

参考材料

Algorithms

https://github.com/jaspervdj/Genus/blob/master/src/genus/FindGirth.java

http://stackoverflow.com/questions/12890106/find-the-girth-of-a-graph

http://webcourse.cs.technion.ac.il/234247/Winter2003-2004/ho/WCFiles/Girth.pdf

  • 大小: 2.9 KB
  • 大小: 9.6 KB
  • 大小: 10.8 KB
  • 大小: 6.8 KB
  • 大小: 7 KB
分享到:
评论

相关推荐

    On the girth of the bipartite graph D(k, q)

    根据提供的文件内容,以下是关于论文《On the girth of the bipartite graph D(k, q)》的知识点梳理: 1. 论文主题与背景:本文研究了一类特殊的代数二分图D(k, q)的围度问题。这类图的围度至少为k+4,并且由...

    matlab girth12rr

    The program constructs girth-twelve column-weight QC-LPDC codes. The rate can be changed by changing k... It guarantees girth of eight. One may need to run the programs many times to get girth of twelve.

    test_girth.rar_LDPC c++_LDPC girth_girth_girth LD_girth LDPC

    **LDPC码与围线长度(Girth)概念** LDPC(Low-Density Parity-Check)码是一种具有低密度奇偶校验矩阵的纠错编码技术,由Robert G. Gallager在1962年首次提出。这种码的奇偶校验矩阵中非零元素的密度相对较低,...

    cycle_search.rar_LDPC girth_LDPC search_find girth_girth_ldpc cy

    本程序的核心功能是针对给定的LDPC奇偶校验矩阵,搜索并计算其girth,这是一项重要的性能指标。 首先,我们要理解什么是girth。在图论中,girth指的是一个无向图中最短的环的边数。对于LDPC码而言,奇偶校验矩阵...

    Measuring length and girth of a tubular shape by quasi-helixes

    Length and girth are central to measure the size of tube shaped objects. This paper extends circular helical curves to general tubular shapes and proposes a novel method for measuring their length and...

    GIRTH8 QC-LDPC MATLAB源码

    本资源是关于构建围长8(Girth 8)列重4(Column Weight 4)的准循环(Quasi-Cyclic, QC)低密度奇偶校验(Low-Density Parity-Check, LDPC)码的MATLAB源码实现。在通信和数据存储领域,LDPC码因其优异的纠错性能而...

    Gallager_girth4.zip

    标题"Gallager_girth4.zip"表明这是一个包含与Gallager算法相关的低密度奇偶校验(LDPC)代码的压缩文件,特别是关注那些具有围长(girth)为4的图结构。在编码理论中,LDPC码是一种纠错码,它们通过构建稀疏的校验...

    The Cayley graph built upon the semigroup of left ideals of a ring (2014年)

    We investigate the interaction between a ring R and the Cayley graph Cay(L(R)) of the semigroup of left ideals of R,as well as subdigraphs of this graph.Graph theoretic properties of these graphs are ...

    LDPC-Codes.zip_LDPC cyclic_girth LDPC_quasi cyclic LDPC_quasi cy

    Construction of One-Coincidence Sequence Quasi-Cyclic LDPC Codes of Large Girth

    Girth-8 column-weight 4 QC-LDPC code: 构造girth-8 column-weight 4 LDPC码-matlab开发

    本文主要关注一种特定类型的LDPC码——girth-8 column-weight 4 QC-LDPC(Quasi-Cyclic Low-Density Parity-Check)码,并探讨其在MATLAB环境下的开发方法。 首先,girth是图论中的一个概念,用于衡量图的最小长度...

    graph0.1.jar

    使用jni调用igraph处理包,生成常见的网络模型:ER,BA,小世界,自定义网络等,并计算网络参数:最短路径,顶点,边,连通性,异质性,有向,领边,girth。

    LDPC_Girth4Test.zip_LDPC_LDPC信道编码_for coding channel_ldpc codes_

    标题中的"LDPC_Girth4Test.zip"和描述指出,这个压缩包包含的是与LDPC信道编码相关的功能子程序和示例,主要针对编码和解码过程。 LDPC码是一种线性分组码,由一组稀疏的校验矩阵定义,其特点在于校验节点和信息...

    Perl语言入门习题答案

    print "the girth of the circle is $g\n"; ``` 这里, `$r` 和 `$g` 是变量,用于存储半径和圆周长的值。 `print` 语句用于输出结果。 2. 用户输入和交互 Perl语言提供了多种方式来获取用户输入,例如使用 `...

    girth:适用于Python的项目响应理论软件包

    G eorgia Tech 一世tem [R 回应钍ory Girth是一个python软件包,用于估计项目响应理论(IRT)参数。 此外,还支持合成IRT数据生成。 以下是可用功能的列表,有关更多信息,请访问GIRTH。 对贝叶斯模型感兴趣? 出 。...

    LDPC 码的 Girth 4 测试:我们需要知道 H 的 Girth 4 会导致较差的 BER 性能。 该程序可以测试是否-matlab开发

    最近,我们发现一些已发表的构建 LDPC 码的程序没有关注 Girth 测试问题,这不会使 LDPC Codec 的实现具有良好的解码 BER。 因此,我们发布了一个简单的程序来为 LDPC 码的周长 4 测试提供一个工具。 在程序中输入...

    Python库 | girth_mcmc-0.6.0-py3-none-any.whl

    资源分类:Python库 所属语言:Python 资源全名:girth_mcmc-0.6.0-py3-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

Global site tag (gtag.js) - Google Analytics