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

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

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

相关文章

  • apache SHTML网页SSI使用详解

    Apache SSI 网页 SHTML 使用详解 SSI 简介 SSI,Server Side Includes,也称为服务器端包含。SSI 是一种在 Web 服务器上进行的处理方式,它能够对页面进行特殊处理,并将处理后的结果输出到客户端。对于 Apache HTTP Server,SSI 可以通过 mod_include 模块实现。 SHTML 简介 SH…

    Java 2023年6月15日
    00
  • H5用户注册表单页 注册模态框!

    那么首先我们需要了解一下“H5用户注册表单页 注册模态框”的含义。这是一种用于网站或应用程序上的用户注册页面,同时也可以使用JavaScript模态框来实现更好的用户体验。 接下来,我们将通过以下步骤来实现这种表单页面和模态框的创建。 步骤1:创建HTML页面 我们可以通过写HTML代码来创建用户注册表单页面。可以使用<form>标签来包含输入字…

    Java 2023年6月15日
    00
  • Spring引入外部属性文件配置数据库连接的步骤详解

    首先需要说明的是 Spring 引入外部属性文件配置数据库连接的过程非常简单,只需要遵循下面的几个步骤即可。 1. 创建属性文件 首先需要在项目的某个目录下创建一个属性文件,比如我们创建一个 db.properties 文件,用于存储数据库连接的相关信息,示例代码如下: jdbc.driver=com.mysql.jdbc.Driver jdbc.url=j…

    Java 2023年6月16日
    00
  • 全面详解Maven打包及其相关插件和高级特性

    全面详解Maven打包及其相关插件和高级特性 Maven打包概述 Maven 是一个基于项目对象模型(POM)的构建工具,能有效地管理项目的构建和依赖。Maven 提供了相应的插件,它们可以帮助我们更方便地进行项目的打包(package)。而打包也是 Maven 项目的必要过程之一,我们能够通过打包将项目打包成可执行的 jar 包、war 包、zip 包等等…

    Java 2023年5月20日
    00
  • springmvc集成使用redis过程

    在 Spring MVC 中集成使用 Redis 非常简单,Redis 是一个高性能的键值对存储数据库,它可以帮助我们更方便地存储和管理数据。本文将详细讲解 Spring MVC 集成使用 Redis 的完整攻略,包括如何配置 Redis、如何使用 RedisTemplate 和 JedisTemplate,并提供两个示例说明。 配置 Redis 在 Spr…

    Java 2023年5月18日
    00
  • spring boot集成shiro详细教程(小结)

    Spring Boot集成Shiro是一个非常常见的需求,它可以帮助我们更好地管理应用程序的安全性。以下是Spring Boot集成Shiro的完整攻略: 添加Shiro依赖 在Spring Boot中,我们可以使用Maven或Gradle来添加Shiro依赖。以下是一个Maven的示例: <dependency> <groupId>…

    Java 2023年5月15日
    00
  • Perl使用Tesseract-OCR实现验证码识别教程

    下面我将为您详细讲解如何使用Perl语言配合Tesseract-OCR开源库实现验证码识别。整个过程共分为以下几个步骤: 安装Tesseract-OCR 安装Perl模块 获取验证码图片 预处理图片 使用Tesseract-OCR进行识别 整合以上步骤 接下来,我们将一步一步来看每个步骤的详细说明。 安装Tesseract-OCR Tesseract-OCR…

    Java 2023年5月26日
    00
  • 浅谈SpringMVC国际化支持

    接下来我将详细讲解“浅谈SpringMVC国际化支持”的完整攻略,包括以下内容: 什么是SpringMVC国际化支持 如何使用SpringMVC国际化支持 示例说明:如何在SpringMVC中实现国际化 什么是SpringMVC国际化支持 SpringMVC国际化支持是一种用于支持跨地区和语言的Web应用程序的技术,它可以将Web应用程序的文本信息本地化,以…

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