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

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

最小树形图(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日

相关文章

  • Spring超详细讲解事务

    Spring超详细讲解事务 什么是事务 事务是指一个操作序列,该操作序列中的所有操作都必须全部执行成功或全部执行失败。事务支持保证数据库的一致性、完整性和隔离性。 Spring事务的优点 在使用Spring进行数据库操作时,使用Spring事务能够带来以下优点: Spring事务对所有的数据库访问代码提供了一致的编程模型 Spring事务可以将数据库事务的边…

    Java 2023年5月19日
    00
  • Java注解机制之Spring自动装配实现原理详解

    下面是详细的攻略。 Java注解机制之Spring自动装配实现原理详解 什么是Spring自动装配 Spring是一个开源框架,通过Spring框架,我们可以快速、简便地开发Java企业应用程序。其中,Spring IoC容器可以实现对象之间的依赖注入。Spring IoC容器可以根据注解或XML配置文件来管理和装配Bean。而Spring自动装配就是IoC…

    Java 2023年5月19日
    00
  • 如何使用并发集合?

    如何使用并发集合? 在开发中,我们常遇到多个线程同时使用共享数据的情况,这时我们需要使用并发集合来确保线程安全。Java并发集合提供了线程安全的工具类,我们可以在多线程环境下使用这些工具类来保证线程安全。Java中有多种并发集合可以使用,如ConcurrentHashMap、ConcurrentSkipListMap、CopyOnWriteArrayList…

    Java 2023年5月10日
    00
  • 使用Python脚本对Linux服务器进行监控的教程

    接下来我会详细讲解如何使用Python脚本对Linux服务器进行监控的完整攻略。 1. 确定监控内容 在开始编写Python脚本之前,需要确定要监控的内容。比如我们可以监控Linux服务器的 CPU 使用率、内存使用率、磁盘占用情况、网络连接数等等。这里以 CPU 使用率为例。 2. 安装Python 在开始编写Python脚本之前,需要确保服务器中拥有Py…

    Java 2023年5月20日
    00
  • 微信小程序模板template简单用法示例

    微信小程序模板template简单用法示例 什么是小程序模板? 小程序模板是一种可复用的代码结构,可以在多个页面中使用。它包含了一些 HTML、CSS、JavaScript 代码,用于渲染页面元素。 如何使用小程序模板? 在微信小程序中,使用小程序模板需要遵循以下步骤: 在 *.wxml 文件中引入模板:使用 wxml 标签的 import 属性,将需要引入…

    Java 2023年5月23日
    00
  • editplus配置java编程环境详细介绍

    EditPlus配置Java编程环境详细介绍 EditPlus是一款文本编辑器,它可以为Java编程者提供良好的编程环境。以下是EditPlus的Java编程环境配置攻略,包括Java 开发工具包(JDK)和编译器环境的配置。 JDK安装 首先,我们需要下载最新的JDK。当前最新版本是JDK 16。通过Oracle官网下载JDK 安装程序并开始安装过程。 安…

    Java 2023年5月23日
    00
  • Springboot 配置SqlSessionFactory方式

    在Spring Boot中,我们可以使用多种方式来配置SqlSessionFactory。以下是两种常见的方式: 1. 使用MyBatis-Spring-Boot-Starter MyBatis-Spring-Boot-Starter是一个官方支持的MyBatis集成Spring Boot的插件,它可以帮助我们快速集成MyBatis和Spring Boot。…

    Java 2023年5月14日
    00
  • 类加载的生命周期包括哪些阶段?

    以下是关于类加载的生命周期包括哪些阶段的详细讲解: 类加载的生命周期包括哪些阶段? 类加载的生命周期包括以下几个阶段: 加载(Loading):将类的字码加载到内存中。 链接(Linking):将类的二进制数据合并到 Java 运行时环境中。 验证(Verification):验证的字节码是否符合 Java 虚拟机规范。 准备(Preparation):为类…

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