一、七桥问题:
欧拉回路:如果每一个点所谅解的桥都是偶数座,则从任意一陆地出发,必能通过每座桥恰好一次回到出发地
二、图论的基本概念:
无向图:没有方向的图记为:G = (V,E)
有向图:他的路线是有方向的
子图:保留所有的点,去掉一部分的边
网路图:
* 各边赋予一定的物理量,如果是距离就叫做网络图或者赋权图
* 所赋予的物理量叫做权
* 权可以是:距离,时间,成本
初等链:定点和边相互交替出现的序列。
路:内部点不相同的链
圈:起点和终点相同的链叫做圈
回路:起点和终点相同的路叫做回路
连通图:在图中,任意两点之间都有一条链相连,叫做连通图,否则就是非连通图
非连通图可以由多个连通图构成
简单图:没有环和多重边的图是简单图
树:不含圈的连通图
树的基本性质
任意两点之间有且只有一条链
若树有p个顶点,则共有q = p-1条边
若图是连通的,且q = p-1,则该图不含圈,因此是树
若图不含圈,且q = p-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. Dijkstra算法,标号法,适用于简单图
2. Floyd算法,求任意两点间的最短路
3. Ford算法,修正标号法,适用于具有复权的网络 - 其他问题:
- 网络流问题
- 最大流问题
- 最小流问题
- …
- 匹配问题
- 其他经典问题
- 欧拉图、哈密尔顿图
- 中国邮递员问题
- 旅行商问题
- …
单旅行商问题求解的近似算法:
- 启发式算法
- 遗传算法
- 模拟退火算法
- 神经网络与人工智能
- 网络流问题
(ps:就写这么多了吧,后面算法等我看懂了再补吧)