栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

12.3 Reverse-Delete算法

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

12.3 Reverse-Delete算法

文章目录
  • 算法描述
  • Python实现
  • Python测试代码

算法描述

  算法的核心思想比较简单,与前三个算法都不同,它是把边按长度逆序排序,每次删除最长的边,直到图变成树为止。我举个例子,以下是图:

  最长的是10,删掉:

  接下来就是长度为9的两个了,删掉,没问题的:


  接下来就是为8的,删除一个:

  剩下的这个长度为8的可不能删除了,因为删除了就不连通了。那就还剩下长度为7的,删掉它:

  还有长度为6的,完全可以删除,但是删除之后,边的数量就是 n − 1 n-1 n−1了,满足树的条件,不能继续删除了:

Python实现

  原理清楚之后,代码就任意写了,以下是python代码:

# _*_ coding:utf-8
import functools


class Edge:

    def __init__(self, to, weight):
        self.__to = to
        self.__weight = weight

    @property
    def to(self):
        return self.__to

    @property
    def weight(self):
        return self.__weight

    def __str__(self):
        return f'->{self.__to}(w={self.__weight})'

    def __repr__(self):
        return f'->{self.__to}(w={self.__weight})'


# wu
class WeightedGraph:
    def __init__(self, vertices, edges, pos):
        self.__vertices = vertices
        self.__edges = edges
        # 用于图形化
        self.__pos = pos

    @property
    def vertices(self):
        return self.__vertices

    @property
    def edges(self):
        return self.__edges

    def reverse_delete(self):
        all_edges = []
        for i, edges in enumerate(self.__edges):
            for edge in edges:
                if i > edge.to:
                    all_edges.append((i, edge))
        all_edges.sort(key=functools.cmp_to_key(lambda x, y: x[1].weight - y[1].weight))
        # 拷贝一套边
        a = [edges[:] for edges in self.__edges]
        x = WeightedGraph(self.__vertices, a, pos=self.__pos)
        n = len(self.__vertices)
        while x.is_connected() and len(all_edges) > n - 2:
            edge = all_edges.pop()
            # 双向删除边
            f = edge[0]
            t = edge[1].to
            if edge[1] in a[f]:
                a[f].remove(edge[1])
            reversed_edge = None
            for i, e in enumerate(a[t]):
                if e.to == f:
                    a[t].pop(i)
                    reversed_edge = e
                    break
            if not x.is_connected():
                # 加回去
                a[f].append(edge[1])
                a[t].append(reversed_edge)
            else:
                print(len(all_edges), x.to_dot())
        return a

    WHITE = 0
    GRAY = 1
    BLACK = 2

    def is_connected(self):
        colors = [WeightedGraph.WHITE for _ in self.__vertices]
        colors[0] = WeightedGraph.GRAY
        stack = [0]
        count = 0
        while len(stack) > 0:
            u = stack.pop()
            count += 1
            for v in self.__edges[u]:
                if colors[v.to] == WeightedGraph.WHITE:
                    stack.append(v.to)
                    colors[v.to] = WeightedGraph.GRAY
            colors[u] = WeightedGraph.BLACK
        return count == len(self.__vertices)

    def to_dot(self):
        pos = self.__pos
        dot_s = 'graph s {ntlayout=fdpn'
        for i, v in enumerate(self.__vertices):
            dot_s += f't"{v}"[pos="{pos[i]}"];n'
        for i, e in enumerate(self.__edges):
            for t in e:
                if t.to < i:
                    continue
                dot_s += f't"{self.__vertices[i]}"--"{self.__vertices[t.to]}"[label="{t.weight}"];n'
        dot_s += '}n'
        return dot_s

Python测试代码
import unittest

from com.youngthing.graph.reverse_delete import Edge, WeightedGraph

class ReverseDeleteTestCase(unittest.TestCase):
    def test_reverse_delete(self):
        # 做一张图
        vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', ]
        # 设计容量
        edges = [
            [Edge(1, 4), Edge(2, 8), ],  # a
            [Edge(0, 4), Edge(2, 9), Edge(3, 8), Edge(4, 10)],  # B
            [Edge(0, 8), Edge(1, 9), Edge(3, 2), Edge(5, 1)],  # C
            [Edge(1, 8), Edge(2, 2), Edge(4, 7), Edge(5, 9)],  # D
            [Edge(1, 10), Edge(3, 7), Edge(5, 5), Edge(6, 6)],  # E
            [Edge(2, 1), Edge(3, 9), Edge(4, 5), Edge(6, 2)],  # f
            [Edge(4, 6), Edge(5, 2)],  # g
        ]
        pos = ["0,0!", "2,1!", "2,-1!", "4,0!", "6,1!", "6,-1!", "8,0!", ]
        fn = WeightedGraph(vertices, edges, pos)

        print(fn.to_dot())

        tree = fn.reverse_delete()
        print(WeightedGraph(vertices, tree, pos).to_dot())


if __name__ == '__main__':
    unittest.main()

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/822405.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号