Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在理解和实现Ford Fulkerson算法方面有困难_Java_Algorithm_Ford Fulkerson - Fatal编程技术网

Java 在理解和实现Ford Fulkerson算法方面有困难

Java 在理解和实现Ford Fulkerson算法方面有困难,java,algorithm,ford-fulkerson,Java,Algorithm,Ford Fulkerson,我试图用Java实现Ford Fulkerson算法。到目前为止,我有一个带有节点和边的图。节点包含ID字符串和边的邻接列表。边包含容量及其指向的节点 我试图理解Wikipedia页面上的psudo代码以及如何实现它(我正在使用Java)。到目前为止,我的理解是: 首先,我将图形中所有边的流设置为零。(什么是表示流的好方法?直接在图形的边中作为变量?) 第二步是创建残差图,这是一个网络,其中边具有残差容量:容量-流量(在“法线图”中对应边的容量)。然后,使用此残差图找到从源到接收器的路径,并找到

我试图用Java实现Ford Fulkerson算法。到目前为止,我有一个带有节点和边的图。节点包含ID字符串和边的邻接列表。边包含容量及其指向的节点

我试图理解Wikipedia页面上的psudo代码以及如何实现它(我正在使用Java)。到目前为止,我的理解是:

  • 首先,我将图形中所有边的流设置为零。(什么是表示流的好方法?直接在图形的边中作为变量?)

  • 第二步是创建残差图,这是一个网络,其中边具有残差容量:容量-流量(在“法线图”中对应边的容量)。然后,使用此残差图找到从源到接收器的路径,并找到沿此路径的最小容量。(这就是事情变得非常棘手的地方,我应该为残差图创建一个全新的图,还是应该在原始图中以某种方式表示它?最好的方法是什么?)

  • 重复步骤2,直到找不到路径,但每次找到路径时,您都要执行步骤3和4:

  • 对于路径上的每条边,添加步骤2中的最小值

  • 对于路径相反方向的每条边,减去步骤2中的最小值

  • 第3步和第4步让我困惑,因为我觉得在一个方向上加和在相反方向上减是一样的。这些加法和减法是在图中进行的,对吧,不是残差图


    如果您能提供帮助,我将不胜感激。我已经想了好几个小时了,但我似乎无法理解它。

    您可能应该首先使用密集图来实现这一点。这样,可以假设在每对不同顶点之间的每个方向上都有一条边。可以将边上的函数表示为| V | x | V |矩阵。特别是,容量和流量的声明非常简单:

    int[][] cap = new int[numverts][numverts];
    int[][] flow = new int[numverts][numverts];
    
    一个有用的技巧是将沿边缘
    vw
    k
    单元流表示为
    a
    v
    w
    的流,以及
    -a
    w
    v
    的流。这样,您就不必担心扩展路径的每一条边是向前推动更多的流还是向后推动更少的流。如果这样做,您可以通过简单的
    cap[v][w]-flow[v][w]
    计算沿
    vw的剩余容量

    使用这种表示法,在稠密图中查找增广路径成为广度优先搜索,在稠密图中,当
    cap[v][w]>flow[v][w]
    时,存在从
    v
    w
    的边。这是相当直接地执行的

    因为您使用的是java,所以应该注意它的每对象开销。您描述的边缘结构不仅包含两个int(或指针)和两个double,还包含GC信息、klass指针和监视器等内容。这是几十个额外的字节,很容易将对象的大小增加一倍或三倍

    当您开始让代码使用稀疏图时,静态稀疏图的更好表示形式如下所示:

    int[] from = new int[numverts+1];
    int[] to = new int[numedges];
    
    按“自”顶点对边进行排序。
    from
    数组的
    i
    th条目是第一条边的索引,其“from”顶点是
    i
    th顶点或更高的顶点。末尾有一个额外的条目,您应该将其设置为
    numedges
    ;当您想要在离开给定顶点的所有边上循环时,它非常方便

    因为您正在进行流,所以您还需要存储后向边,所以有一个

    int[] rev = new int[numedges];
    
    存储每条边的反向边索引。现在,您可以在边上表示任意函数,例如
    cap
    flow
    ,如下所示:

    int[] cap = new int[numedges];
    int[] flow = new int[numedges];
    

    因此,是否将这些属性存储在
    边缘
    结构中是没有意义的,因为
    边缘
    结构已经消失。

    您可能应该首先使用密集图来实现这一点。这样,可以假设在每对不同顶点之间的每个方向上都有一条边。可以将边上的函数表示为| V | x | V |矩阵。特别是,容量和流量的声明非常简单:

    int[][] cap = new int[numverts][numverts];
    int[][] flow = new int[numverts][numverts];
    
    一个有用的技巧是将沿边缘
    vw
    k
    单元流表示为
    a
    v
    w
    的流,以及
    -a
    w
    v
    的流。这样,您就不必担心扩展路径的每一条边是向前推动更多的流还是向后推动更少的流。如果这样做,您可以通过简单的
    cap[v][w]-flow[v][w]
    计算沿
    vw的剩余容量

    使用这种表示法,在稠密图中查找增广路径成为广度优先搜索,在稠密图中,当
    cap[v][w]>flow[v][w]
    时,存在从
    v
    w
    的边。这是相当直接地执行的

    因为您使用的是java,所以应该注意它的每对象开销。您描述的边缘结构不仅包含两个int(或指针)和两个double,还包含GC信息、klass指针和监视器等内容。这是几十个额外的字节,很容易将对象的大小增加一倍或三倍

    当您开始让代码使用稀疏图时,静态稀疏图的更好表示形式如下所示:

    int[] from = new int[numverts+1];
    int[] to = new int[numedges];
    
    按“自”顶点对边进行排序。
    from
    数组的
    i
    th条目是第一条边的索引,其“from”顶点是
    i
    th顶点或更高的顶点。末尾有一个额外的条目,您应该将其设置为
    numedges
    ;当您想要在离开给定顶点的所有边上循环时,它非常方便

    因为您在做flow,所以需要向后存储