Python深度学习-有向图合并、排序、最长路径计算

news2024/11/25 23:17:08

一、有向图方向、权重表示方法

Python通常使用有向图中边的起点和终点来表示边的方向。例如,如果有一条从节点A到节点B的边,则可以使用以下方式表示该有向边:

graph = {
    'A': {'B': 1}
}

在这个例子中,节点'A'和节点'B'之间存在一条权重为1的边,它的方向是从'A'指向'B'。这表示从节点'A'可以到达节点'B',但不一定反过来。如果要表示从节点'B'到节点'A'的边,需要另外定义一个字典:

graph = {
    'A': {'B': 1},
    'B': {'A': 2}
}

在这个例子中,节点'A'和节点'B'之间存在两条边。第一条是从'A'到'B',权重为1,第二条是从'B'到'A',权重为2。注意,这两条边是不同的,因为它们的方向不同。

二、有向图合并原理

有向图合并指的是将多个有向图合并成一个有向图的过程。这种操作在图数据处理中比较常见,例如将多个社交网络中的用户关系、兴趣爱好等信息进行整合,以便进行更全面、准确的分析。

有向图合并的原理主要涉及节点合并和边合并两个方面。

节点合并:当有多个有向图的节点表示同一个实体时,需要将这些节点合并成一个节点,避免在后续操作中出现重复计算问题。节点合并可以使用哈希表等数据结构实现,将每个节点关联到对应的实体上,通过哈希表查找实体对应的节点进行合并。

边合并:当有多个有向图中的两个节点之间存在相同的边时,需要将这些边合并成一条边,以避免重复计算。边合并可以根据具体情况进行不同的处理。例如,如果边的权重值相同,则可以直接合并;如果不同,则可以选择采用加权平均值、加权求和等方法来合并边的权重值。

以下是Python实现有向图合并的示例代码:

def merge_digraphs(graphs):
    # 合并有向图
    merged_graph = {}
    # 记录每个实体对应的节点
    entity_to_node = {}
    for graph in graphs:
        for node, neighbors in graph.items():
            # 合并节点
            if node in entity_to_node:
                curr_node = entity_to_node[node]
            else:
                curr_node = node
                entity_to_node[node] = curr_node

            # 合并边
            for neighbor, weight in neighbors.items():
                if neighbor in entity_to_node:
                    curr_neighbor = entity_to_node[neighbor]
                else:
                    curr_neighbor = neighbor
                    entity_to_node[neighbor] = curr_neighbor
                if curr_node not in merged_graph:
                    merged_graph[curr_node] = {}
                if curr_neighbor in merged_graph[curr_node]:
                    merged_graph[curr_node][curr_neighbor] += weight
                else:
                    merged_graph[curr_node][curr_neighbor] = weight

    return merged_graph

arr_graph1 =  [
    {'A': {'B': 3, 'C': 6},
     'B': {'C': 2, 'D': 1},
     'C': {'D': 1},
     'D': {}}
]

arr_graph2 =  [
    {'A': {'B': 3, 'C': 6},
     'B': {'C': 2, 'D': 1},
     'C': {'D': 1},
     'D': {}},
    {'A': {'B': 1, 'C': 1},
         'B': {'C': 1, 'D': 1},
         'C': {'D': 1},
         'D': {}}
]
print(merge_digraphs(arr_graph1))
print(merge_digraphs(arr_graph2))


运行结果:

 

graphs是待合并的多个有向图,每个有向图用邻接表形式表示。在合并节点时,首先判断该节点是否已经存在于之前的有向图中,如果是,则直接将当前节点关联到该实体上;否则,将当前节点作为新的节点,并将其关联到对应的实体上。在合并边时,如果两个节点之间的边已经存在,则将其权重值相加;否则,将其作为新的边添加到合并后的有向图中。

三、有向图最长路径算法

下面是一个Python实现有向图最长路径计算的代码示例:

from collections import deque

def topological_sort(graph):
    # 对有向图进行拓扑排序
    in_degree = {v: 0 for v in graph}  # 记录每个节点的入度
    for node in graph:
        for neighbor in graph[node]:
            in_degree[neighbor] += 1

    queue = deque([node for node in in_degree if in_degree[node] == 0])
    result = []
    while queue:
        node = queue.popleft()
        result.append(node)
        for neighbor in graph[node]:
            in_degree[neighbor] -= 1
            if in_degree[neighbor] == 0:
                queue.append(neighbor)

    if len(result) != len(graph):  # 存在环
        return None
    return result

def longest_path(graph, start, end):
    # 计算有向图中从start到end的最长路径
    topological_order = topological_sort(graph)
    print(f'有向图拓扑排序结果:{topological_order}')

    dist = {node: float('-inf') for node in graph}
    dist[start] = 0
    prev = {node: None for node in graph}

    for node in topological_order:
        if node == end:
            break
        if dist[node] != float('-inf'):
            for neighbor in graph[node]:
                new_dist = dist[node] + graph[node][neighbor]
                if new_dist > dist[neighbor]:
                    dist[neighbor] = new_dist
                    prev[neighbor] = node

    # 生成路径
    path = []
    node = end
    while node is not None:
        path.append(node)
        node = prev[node]
    path.reverse()

    return dist[end], path



# 举个例子
graph = {'A': {'B': 3, 'C': 6},
         'B': {'C': 2, 'D': 1},
         'C': {'D': 1},
         'D': {}}
length, path = longest_path(graph, 'A', 'D')
print(f"最长路径为{path},路径长度(权重)为{length}")

运行结果:

 

有向图:

 

 

这个例子中,我们先使用topological_sort函数对有向图进行拓扑排序,然后依次计算每个节点的最长路径和路径终点,并使用prev字典记录每个节点在最长路径上的前驱节点。最后,我们生成从起点到终点的最长路径。这个算法的时间复杂度为O(V+E),其中V是节点数量,E是边数量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/746651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

谷歌插件下载Redux DevTools管理Redux数据

我们在做 react-redux开发时 很多时候可能无法确定自己的数据有没有成功导进来 这里就有个不错的谷歌插件推荐给大家 大家可以下载我的资源 谷歌插件Redux DevTools 这里 我们打开 Google Chrome浏览器 然后 直接在谷歌浏览器上访问 chrome://extensions/ 如果你的第一次进入 …

【网络安全】学过编程就是黑客?

我们不可否认的是黑客为我们带来了巨大的财产损失于危机,即使其最初的思想是正确的。 个人主页:【😊许思王】 文章目录 前言黑客 💻起源🚗发展👣黑客守则(真的假的🤔)黑…

合并cyclonedx格式的bom文件

1.工具下载 https://github.com/CycloneDX/cyclonedx-cli/releases 2.操作记录 Usage: cyclonedx [options] [command] Options: --version Show version information -?, -h, --help Show help and usage information Commands: add Add information to a BOM (currently…

【图像处理】:相机对焦的原理和实现方法

相机对焦的原理和实现方法 1 原理介绍:1.1点扩散函数“原理:1.2 测距原理:对焦的本质是测距:1.3.相位检测只原理: 2.实现方法2 1 原理介绍: 对焦有三种思路: 1.1点扩散函数“原理: 也就是观测画面中线条边缘的对比度,对比度最高…

微信小程序代码审核,提示需要添加文娱-其他视频类目

这个解决办法有三个 一个是按照指引去申请资质 第二个是通过后端写一个鉴权接口,审核时候去通过接口返回的布尔值去隐藏掉视频模块,通过后再显示出来 第三个是服务除视频内容外还存在其他形式的情况可以通过引入第三方视频插件来解决,但是…

初识Golang,集简洁与性能与一体的语言

文章目录 一、Go语言介绍二、Go语言特性三、Go语言用途四、开发环境搭建五、建立工作区并创建Go程序六、入口文件基本代码介绍七、go命令介绍7.1 基本命令7.2 build 与 run命令7.3 install命令介绍 八、命名规范8.1 变量规范定义8.2 关键字8.3 保留字8.4 需要注意的问题 道阻且…

AIGC 爆火,浪潮信息要做大模型的数据存储大底座

AIGC 在 2023 年爆火,各类大模型层出不穷,参数动辄达到千亿数量级。这些背后,数据的类型和形式也走向复杂多样。例如大模型会采用到我们真实物理世界中的文字、视觉、音频、3D、雷达、多谱等复杂多样的不同模态信号和数据,数据则又…

【Android复习笔记】系统进程(一)

Android 系统进程有哪些 先来一个整体结构图从宏观上理解Android系统的进程结构布局: 这里我们简单总结一下: 系统的第一个进程其实是0号进程(又叫swapper进程/Idle进程) 0号进程fork出了1号进程(init进程)和2号进程(kthreadd进程) 1号进程是所有普通用户进程的祖先,2号进程…

利用Adobe Acrobat DC实现图片和PDF互相转换

一、图片转PDF 可以实现多张或者单张图片转PDF! 这个需要使用到Adobe Acrobat DC的文件合并功能,因为Adobe Acrobat DC的文件合并,不仅可以合并多个pdf文件,也支持合并图片文件。 如图,直接选中多张图片合成即可: 添…

微服务系列文章之 Redisson实现分布式锁(3)

一、概述 1、技术架构 项目总体技术选型 SpringBoot2.4.5 Maven3.5.4 Redisson3.5.4 lombok(插件)2、加锁方式 该项目支持 自定义注解加锁 和 常规加锁 两种模式 自定义注解加锁 DistributedLock(value"goods", leaseTime5)public String lockDecreaseStock(…

84. 求1+2+…+n

链接: 链接 题目: 求 12…n12…n,要求不能使用乘除法、forfor、whilewhile、ifif、elseelse、switchswitch、casecase 等关键字及条件判断语句 (A?B:C)(A?B:C)。 数据范围 1≤n≤500001≤n≤50000。 样例 输入:10输出&#xff1…

【MySQL】不允许你不会使用组合查询

🎬 博客主页:博主链接 🎥 本文由 M malloc 原创,首发于 CSDN🙉 🎄 学习专栏推荐:LeetCode刷题集 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正&#xff0…

ASEMI-1N4007是什么二极管,1N4007是什么类型的二极管

编辑-Z 1N4007是一种常见的二极管,属于快恢复二极管(Fast Recovery Diode)的一种。它是一种高压、高电流的整流二极管,常用于电源电路中的整流器。1N4007的最大反向电压为1000V,最大正向电流为1A,具有较低…

第十七章 原理篇:Deformable DETR

参考教程: 论文:https://arxiv.org/pdf/2010.04159.pdf 源码:https://github.com/fundamentalvision/Deformable-DETR 文章目录 Deformable ConvDeformable DETR计算量MethodDeformable Attention ModuleDeformAttn计算量Multi-scale Defor…

JVM学习笔记(二)

学习黑马视频:01_什么是jvm_哔哩哔哩_bilibili 一、JVM内存结构 程序计数器 虚拟机栈 本地方法栈 堆 方法区 程序计数器、栈、本地方法栈,都是线程私有的。堆、方法区是线程共享的区域。 1. 虚拟机栈(JVM Stacks) 1&#xff09…

avue 自定义按钮修改后触发表单自带的校验方法;avue表单提交

代码&#xff1a; <avue-form :option"option" v-model"publishForm" ref"publishForm" submit"handleSubmit"><template slot-scope"{size}" slot"menuForm"><el-button :size"size" …

LayUi之选项卡的详解(附源码讲解)

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于LayUi的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.选项卡是什么 二.选项卡在什么时候使用…

最新软件工程毕业设计选题推荐100例

文章目录 0 简介1 如何选题2 最新软件工程毕设选题3 最后 0 简介 学长搜集分享最新的软件工程业专业毕设选题&#xff0c;难度适中&#xff0c;适合作为毕业设计&#xff0c;大家参考。 学长整理的题目标准&#xff1a; 相对容易工作量达标题目新颖 1 如何选题 最近非常多的…

IDEA debug 断点调试技巧

1、首先看下IDEA中Debug模式下的界面&#xff1a; ① 以Debug模式启动服务&#xff0c;左边的一个按钮则是以Run模式启动。在开发中&#xff0c;我一般会直接启动Debug模式&#xff0c;方便随时调试代码。 ② 断点&#xff1a;在左边行号栏单击左键&#xff0c;或者快捷键Ctrl…

Git教程-廖雪峰-个人归纳更新总结

文章目录 前言Git简介&#xff1a;Git的诞生&#xff1a;集中式和分布式 安装Git&#xff1a;创建版本库时光穿梭机(*)版本回退撤销修改删除文件 远程仓库&#xff1a;添加远程仓库&#xff1a;删除远程库与本地库的链接&#xff1a; 从远程库克隆(*) 使用GitHub 前言 日常需要…