图算法总结(判断有环、最短路径)

有向图判断有环

拓扑排序

这时有些点的入度减少了,于是再拿出当前所有入度为0的点放在已经排序的序列后面,然后删除:

因为是有向无环图,而且删除操作不会产生环,所以每时每刻都一定存在入度为0的点,一定可以不断进行下去,直到所有点被删除。

以下是一个O(m+n)的实现(m,n 分别表示点数和边数)

if __name__ == "__main__":
    v = [[0, 0, 0, 0, 1], [1, 0, 0, 0, 0], [0, 0, 0, 1, 1], [0, 0, 0, 0, 0], [0, 1, 0, 0, 0]]
    e = [[]]
    in_v = {}
    cnt = 0
    visited = set()
    circle = []
    # 计算每个点的入度
    for i in range(len(v)):
        for j in range(len(v)):
            if v[i][j] == 1:
                if j not in in_v.keys():
                    in_v[j] = 0
                in_v[j] += 1

    # 拓扑
    # 入度为0的点,加入到visited中
    change = True
    while change:
        change = False
        for node in range(len(v)):
            if node not in visited and (node not in in_v.keys() or in_v[node] == 0):
                change = True
                visited.add(node)
                for j in range(len(v)):
                    if v[node][j] == 1:
                        in_v[j] -= 1

    # 没有被visited的,即为环
    for node in range(len(v)):
        if node not in visited:
            circle.append(node)

    print(circle)

应用:

给定一堆序列标号(标号用整数),形式为[a,b],表示标号为a,b的两个物体的体积关系满足:a > b,用合适的数据结构存储数据,并判断这堆序列是否有效。(比如[a,b], [b, d], [d, a]这个就不是有效的,因为a > b, b > d, 那么 a > d, 但是最后一个序列说的是 d > a,矛盾了。)

思路:

题目实际是,求图中是否有环,用拓扑结构,把入度为0的结点全部删掉,直到删不动为止。

# 有向图判断有环:拓扑算法
def hasCircel(inputs):
    graph = {}
    in_v = {}
    nodes = set()
    # 用字典存每个点连接的点
    # 保存每个点入度
    for pair in inputs:
        a,b = pair
        nodes.add(a)
        nodes.add(b)
        if a not in graph.keys():
            graph[a] = [b]
        else:
            graph[a].append(b)
        if b not in in_v.keys():
            in_v[b] = 0
        in_v[b] += 1

    # 拓扑判断是否有环:
    # 入度为0的点删去,它相关的出度点入度-1,不断迭代
    nodes = list(nodes)
    visted = [False]*len(nodes)
    change = True
    while change:
        change = False
        for i in range(len(nodes)):
            if not visted[i] and (nodes[i] not in in_v.keys() or in_v[nodes[i]] == 0):
                visted[i] = True
                change = True
                if nodes[i] in graph.keys():
                    connect_nodes = graph[nodes[i]]
                    for node in connect_nodes:
                        in_v[node] -= 1

    for i in range(len(nodes)):
        if not visted[i]:
            return False
    return True

if __name__ == '__main__':
    inputs = [[1, 2], [2, 3], [3, 1]]
    res = hasCircel(inputs)
    print(res)

Dijkstra算法(单源最短路径)

贪心思想实现的,首先把起点到所有点的距离存下来找个最短的,然后松弛一次再找出最短的,所谓的松弛操作就是,遍历一遍看通过刚刚找到的距离最短的点作为中转站会不会更近,如果更近了就更新距离,这样把所有的点找遍之后就存下了起点到其他所有点的最短距离。

具体实现参考:

Dijkstra算法图文详解_black_hole6的博客-CSDN博客_dijkstra算法

Floyd(多源最短路径)

最短路之——弗洛伊德算法(floyd)_shezjoe的博客-CSDN博客_弗洛伊德最短路

bfs/dfs

图的四种最短路径算法_Leslie's Blog-CSDN博客_最短路径算法

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在MATLAB中实现Dijkstra最短路径算法包括以下步骤: 1. 初始化: - 创建一个矩阵 `dist` 用于存储每个节点到起始节点的距离,初始时将所有节点的距离设置为无穷大,除了起始节点的距离设置为0。 - 创建一个矩阵 `visited` 用于标记每个节点是否被访问过,初始时将所有节点的访问状态设置为未访问。 - 创建一个向量 `prev` 用于存储到达每个节点的前一个节点,初始时将所有节点的前一个节点设置为起始节点。 2. 运行Dijkstra算法: - 在 `dist` 中选择距离起始节点最近且未被访问过的节点作为当前节点。 - 更新当前节点的相邻节点的距离,如果通过当前节点到达相邻节点的距离比原先记录的距离更短,则更新 `dist` 中的距离,并将当前节点作为相邻节点的前一个节点。 - 将当前节点标记为已访问。 - 重复以上步骤,直到所有节点都被访问过。 3. 打印最短路径: - 根据 `prev` 向量,从终点节点开始,沿着每个节点的前一个节点逆向查找,直到找到起点节点。 - 将遍历的节点按照逆序存储在一个向量中。 - 输出这个向量即为起点到终点的最短路径。 注意:在实现中,需要根据具体情况对节点和边的表示方式进行调整。 以下是一个简单的示例,假设的邻接矩阵为 `graph`,起始节点为 `start`,终点节点为 `end`: ```matlab function shortestPath(graph, start, end) numNodes = size(graph, 1); dist = inf(1, numNodes); % 用于存储节点到起始节点的距离 visited = false(1, numNodes); % 用于标记节点是否被访问过 prev = zeros(1, numNodes); % 用于存储到达节点的前一个节点 % 初始化起始节点的信息 dist(start) = 0; % 执行Dijkstra算法 for i = 1:numNodes % 在未访问的节点中选择距离起始节点最近的节点 curr = findMinDist(dist, visited); visited(curr) = true; % 更新相邻节点的距离 for j = 1:numNodes if graph(curr, j) > 0 % 判断两节点是否相邻 alt = dist(curr) + graph(curr, j); if alt < dist(j) dist(j) = alt; prev(j) = curr; end end end end % 打印最短路径 path = end; while path ~= start path = [prev(path), path]; end fprintf('最短路径为:%s\n', num2str(fliplr(path))); % 输出逆序的最短路径 end function minNode = findMinDist(dist, visited) minDist = inf; minNode = -1; for i = 1:length(dist) if ~visited(i) && dist(i) < minDist minDist = dist(i); minNode = i; end end end ``` 这是一个基本的Dijkstra最短路径算法的MATLAB实现,并包括了输出最短路径的思路。实际应用中可能需要根据具体问题进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值