最小树形图模板朱刘算法分享

最小树形图模板朱刘算法分享

最小树形图(Minimum Spanning Arborescence)是有向图的一种特殊的生成树,它包含了图中所有的点且仅有一个点入度为0(源点)。朱刘算法是一种求解最小树形图的算法,时间复杂度为$O(VE)$。

以下是朱刘算法的完整攻略:

1. 算法原理

朱刘算法基于”缩点”思想和“基环树”的性质,在每一个生成树已经连出来的点(包括源点)中选择一个代表进行缩点,每次将点进行缩点,并记缩点后连出去的边的最小边权作为这个点的代价,缩点后生成的新图上执行贪心算法来找到最小树形图。如果新图中存在环,就对环进行“缩环”,将环上的若干个点缩成一个点,重新生成一个新图,递归地执行缩点/缩环操作,直到得到一棵树为止。

2. 详细步骤

按照如下步骤执行朱刘算法:

  • 构建一个新图 $G'$,其中新图的顶点与 $G$ 的强连通分量一一对应。
  • 对强连通分量内部进行缩点。这个过程需要在线性时间内完成,并确定构建新图 $G'$ 后,对应的新源点。
  • 对 $G'$ 执行普通的 Prim 或 Kruskal 算法。这两个算法都能在线性时间内找到 $G'$ 的最小生成树。
  • 如果生成的最小树不包含新源点,算法结束。
  • 如果生成的最小树包含新源点,则需要查找环。对于任意一条从新源点开始的出边 $(u,w)$,在缩点后的点集合中,找到 $(u,w)$ 所指向的顶点 $v$。如果 $v$ 已经在环中,则不需要再次寻找环。否则,从 $v$ 开始继续深度遍历,得到一个环,并从中选取一条基本边 e,再执行缩环操作
  • 缩环后需要重新建图。对于原图 $G$ 中的每个顶点,找到新图 $G'$ 中所代表的强连通分量,把该顶点标记为这个分量的代表点,并把这个顶点所在的连通分量的所有边都放进一个集合里。
  • 在这个新的图上,重复步骤3,直到找到一棵不包含新源点的最小生成树。

3. 算法实现

这里提供一个实现朱刘算法的Python代码示例:

import sys
from typing import List, Tuple

INF = sys.maxsize


def add_edge(u: int, v: int, w: int, adj: List[List[Tuple[int, int]]]) -> None:
    adj[u].append((v, w))


def update(son: List[int], delta: List[int], dad: List[int], x: int) -> None:
    delta[x] = INF
    for i in range(len(son)):
        y = son[i]
        if dad[y] == x:
            update(son, delta, dad, y)
            delta[x] = min(delta[x], delta[y])

        delta[x] = min(delta[x], delta[y] - INF)


def zhu_liu(n: int, root: int, edges: List[Tuple[int, int, int]]) -> Tuple[int, List[int]]:
    """zhu_liu algorithm

    Args:
        n (int): total number of vertices
        root (int): root of the minimum spanning arborescence
        edges (List[Tuple[int, int, int]]): edges of the graph, (u, v, w)

    Returns:
        Tuple[int, List[int]]: minimum cost and MST
    """
    m = len(edges)
    dad = [root for _ in range(n)]
    best = [INF for _ in range(n)]
    vis = [False for _ in range(n)]

    for _ in range(n):
        for j in range(m):
            u, v, w = edges[j]
            if best[v] > w and u != v:
                best[v] = w
                dad[v] = u

        for j in range(n):
            if j == root:
                continue
            if best[j] == INF:
                return -1, []
            update([j], best, dad, j)
            for k in range(len(edges)):
                u, v, w = edges[k]
                if dad[u] != u and best[v] == w:
                    dad[v] = u
                    break

        if dad[root] == root:
            return sum(best), dad

        cur = root
        next_ = root
        while vis[cur]:
            cur = dad[cur]
        while not vis[cur]:
            vis[cur] = True
            cur = dad[cur]
        for i in range(n):
            if vis[i]:
                best[i] -= best[cur]
                dad[i] = cur
            else:
                best[i] -= best[next_]

        root = next_

    return -1, []

4. 示例说明

以下是两个使用朱刘算法求解最小树形图的示例:

示例 1:

给定图 $G$,如下所示:

       1      6      7
   o ---> o ---> o ---> o
   | 4    /\     |    / |
2  |    /    \   |  /   |8
   v  /      \  v /    v
   o <---- o <--- o <--- o
      5      3      9

执行朱刘算法后,得到生成的最小树形图如下:

        6          7
    o ---> o ---> o
    |      /       |                  
   2|    /    8    |5  
    v  /          v           
    o <-----------o
         3

示例 2:

给定图 $G$,如下所示:

        3    2    5
    o ---> o ---> o
    | _ 2 /      |                  
   1| _\_/        |1  
    v             v           
    o ------------o
          6

执行朱刘算法后,得到生成的最小树形图如下:

        3          5
    o ---> o ---> o                  
    |            / |                  
   1|          /   |1  
    v        /     v           
    o <-----o <----o
          6      2

参考

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:最小树形图模板朱刘算法分享 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • JBuilder2005单元测试之创建测试固件

    首先,需要说明的是,JBuilder2005已经过时,现在推荐使用更加现代化的Java IDE,例如Eclipse、IntelliJ IDEA等。但是,本篇回答还是会根据题目要求讲解JBuilder2005中如何创建测试固件。 创建测试固件 测试固件可以理解为对于某个类或方法的测试环境的配置和准备,通常包括测试数据的设置、测试对象的初始化等。JBuilder…

    Java 2023年6月15日
    00
  • java的Hibernate框架报错“NonUniqueObjectException”的原因和解决方法

    当使用Hibernate框架时,可能会遇到“NonUniqueObjectException”错误。这个错误通常是由于以下原因之一引起的: 多个实体对象具有相同的标识符:如果您的多个实体对象具有相同的标识符,则可能会出现此错误。在这种情况下,需要检查您的实体对象并确保它们具有唯一的标识符。 会话中存在多个实体对象:如果您的会话中存在多个实体对象,则可能会出现…

    Java 2023年5月4日
    00
  • JS工厂模式开发实践案例分析

    JS工厂模式开发实践案例分析 什么是JS工厂模式 在JavaScript中,工厂模式是一种用于创建对象的设计模式。工厂模式基于工厂方法,即通过调用工厂方法,返回所需的对象实例。在JavaScript中,这种模式非常常见,因为它可以帮助我们快速创建多个相似的对象。 工厂模式的优缺点 优点 工厂模式可以帮助我们将代码组织得更加清晰和易于管理。 工厂模式允许我们复…

    Java 2023年5月26日
    00
  • Java从JDK源码角度对Object进行实例分析

    讲解“Java从JDK源码角度对Object进行实例分析”的攻略如下: 一、分析Object类的源码 先介绍下Object类的源码结构: public class Object { private static native void registerNatives(); static { registerNatives(); } public final …

    Java 2023年5月26日
    00
  • Java泛型机制的程序演示详解

    Java泛型机制的程序演示详解 什么是Java泛型? Java泛型是JDK1.5版本中引入的新特性。它的主要目的是用来规范和简化Java中的类型变量的使用。 在Java泛型出现之前,Java中的类或者方法的参数或者返回值只能使用具体的类型,比如String、Integer等。而Java泛型则提供了一种灵活的方式,可以在定义类或者方法时,以一个类型变量作为参数…

    Java 2023年5月30日
    00
  • Java 如何读取Excel格式xls、xlsx数据工具类

    Java如何读取Excel格式xls、xlsx数据 在Java中,我们可以使用POI库来操作Excel文件,这个库支持读取和写入Excel文件。下面我们将通过两个示例来讲解如何读取Excel格式xls、xlsx数据。 示例1:读取Excel文件中的数据 首先我们需要引入相关依赖。在pom.xml文件中添加以下配置: <dependencies> …

    Java 2023年5月19日
    00
  • 详解Spring Data JPA中Repository的接口查询方法

    Sure!下面是关于“详解Spring Data JPA中Repository的接口查询方法”的完整攻略: 1、什么是Spring Data JPA Spring Data JPA是Spring上建立的一套基于JPA规范的框架,主要用于简化JPA数据访问层的开发,封装了大量复杂的数据访问操作,同时也保证了极高的数据安全性和性能表现。 2、什么是Reposit…

    Java 2023年5月20日
    00
  • spring boot 使用Mybatis-plus查询方法解析

    Spring Boot使用Mybatis-Plus查询方法解析 Mybatis-Plus简介 Mybatis-Plus是一个Mybatis的增强工具,在Mybatis的基础上扩展了一些实用的功能,例如分页、逻辑删除、自动填充等。 配置Mybatis-Plus 在Spring Boot项目中使用Mybatis-Plus需要先配置相关依赖,可以在pom.xml文…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部