数学建模——图论

一、七桥问题:

在这里插入图片描述

	欧拉回路:如果每一个点所谅解的桥都是偶数座,则从任意一陆地出发,必能通过每座桥恰好一次回到出发地

二、图论的基本概念:

无向图:没有方向的图记为:G = (V,E)
在这里插入图片描述
有向图:他的路线是有方向的
在这里插入图片描述
子图:保留所有的点,去掉一部分的边
网路图:
* 各边赋予一定的物理量,如果是距离就叫做网络图或者赋权图
* 所赋予的物理量叫做权
* 权可以是:距离,时间,成本
初等链:定点和边相互交替出现的序列。
路:内部点不相同的链
圈:起点和终点相同的链叫做圈
回路:起点和终点相同的路叫做回路
连通图:在图中,任意两点之间都有一条链相连,叫做连通图,否则就是非连通图
非连通图可以由多个连通图构成
简单图:没有环和多重边的图是简单图
树:不含圈的连通图
树的基本性质
任意两点之间有且只有一条链
若树有p个顶点,则共有q = p-1条边
若图是连通的,且q = p-1,则该图不含圈,因此是树
若图不含圈,且q = p-1,则该图连通,因此是树

三、图论的基本问题及算法

  1. 最小链接问题
    • 解决算法:最小生成树,最小支撑树
      最小生成树算法思路及程序设计
# kruskal寻找最小生成树
# 先确定每一条边链接的节点和距离
# 根据距离对这些边进行排序
# 我们取出所有的点生成图(不留边)
# 然后把排序好的边从低到高取出放入到图中
# 如果形成了回路我们就不再使用这边条边
# 直到我们的边遍历完成或者我们的边达到预期数量


def find(node, root_list):
   # 默认根节点是自己
   root = node
   # 如果根节点不是自己,就进行改变
   while root != root_list[root]:
       root = root_list[root]
   return root


def trange_data(edge, root_list, node_list):
   # 检测我们这两条边的根节点
   root1, root2 = find(edge[0], root_list), find(edge[1], root_list)
   # 如果第一个节点能链接到的点数小于第二个节点能连接到的点数
   # 那么我们第二个才是最大的根节点
   # 为什么这样能找出最大的根节点呢
   # 因为两个节点能相互连接,,也就是说,我们的节点能链接彼此的节点,那么加起来最大的那个自然是最大根节点咯
   if node_list[root1] < node_list[root2]:
       root_list[root1] = root2
   # 反之,则第一个才是最大的根节点
   else:
       root_list[root2] = root1
       # 如果这两个正好相等,就让期中一个+1使得其成为最大的根节点
       if node_list[root1] == node_list[root2]:
           node_list[root1] += 1


def kruskal(edges, N):
   # 对我们的边进行排序
   edges = sorted(edges, key=lambda x: x[-1])
   # 初始化每个点的根节点和他们连通的点的个数,还有最小树的列表
   tree = []
   # 默认他们的根节点就是他们自己
   root_list = [i for i in range(N)]
   node_list = [0]*N
   # 我们知道,N个节点只有N-1条边,我们要设置记录边条数的变量
   count = 0
   # 遍历排序好的边
   for edge in edges:
       # 两个根节点不同才能保留当前遍历的边
       # 设想一下,我们的两个点有相同的根节点,然后根节点能链接到这两个点,如果这两个点还能互相链接不就封闭了
       if find(edge[0], root_list) != find(edge[1], root_list):
           # 如果不同,我们就保留这条边
           tree.append(edge)
           # 开始修改我们的root_list和我们的node_list
           trange_data(edge, root_list, node_list)
           count += 1
       if count == N-1:
           break
   return tree


if __name__ == "__main__":
   # 一个数组表示一条边,前两个表示的是节点,最后一个表示距离
   edges = [
       [0, 1, 6],
       [0, 2, 1],
       [0, 3, 5],
       [2, 1, 5],
       [2, 3, 5],
       [2, 4, 5],
       [2, 5, 4],
       [1, 4, 3],
       [4, 5, 6],
       [5, 3, 2]
   ]


   # 节点数
   Node = 6
   # 引入kruskal
   miniTree = kruskal(edges, Node)
   for node in miniTree:
       print("%d - %d  %d" % (node[0], node[1], node[2]))

# 结果为:
# 0 - 2  1
# 5 - 3  2
# 1 - 4  3
# 2 - 5  4
# 2 - 1  5
  1. 最短路问题:
    选定一个终点和一个起点,从图中找到从起点到终点的最短路径
    经典算法:
    1. Dijkstra算法,标号法,适用于简单图
    2. Floyd算法,求任意两点间的最短路
    3. Ford算法,修正标号法,适用于具有复权的网络
  2. 其他问题:
    • 网络流问题
      • 最大流问题
      • 最小流问题
    • 匹配问题
    • 其他经典问题
      • 欧拉图、哈密尔顿图
      • 中国邮递员问题
      • 旅行商问题

      • 单旅行商问题求解的近似算法:
    • 启发式算法
    • 遗传算法
    • 模拟退火算法
    • 神经网络与人工智能

(ps:就写这么多了吧,后面算法等我看懂了再补吧)

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值