问题

思路说明:

解决1(Python)

解决2(Python)

  1. #coding:utf-8
  2. import unittest
  3. class UnionFind:
  4. """
  5. UnionFind的实例:
  6. Each unionFind instance X maintains a family of disjoint sets of
  7. hashable objects, supporting the following two methods:
  8. - X[item] returns a name for the set containing the given item.
  9. Each set is named by an arbitrarily-chosen one of its members; as
  10. long as the set remains unchanged it will keep the same name. If
  11. the item is not yet part of a set in X, a new singleton set is
  12. created for it.
  13. - X.union(item1, item2, ...) merges the sets containing each item
  14. into a single larger set. If any item is not yet part of a set
  15. in X, it is added to X as one of the members of the merged set.
  16. """
  17. def __init__(self):
  18. """Create a new empty union-find structure."""
  19. self.weights = {}
  20. self.parents = {}
  21. def __getitem__(self, object):
  22. """Find and return the name of the set containing the object."""
  23. # check for previously unknown object
  24. if object not in self.parents:
  25. self.parents[object] = object
  26. self.weights[object] = 1
  27. return object
  28. # find path of objects leading to the root
  29. path = [object]
  30. root = self.parents[object]
  31. while root != path[-1]:
  32. path.append(root)
  33. root = self.parents[root]
  34. # compress the path and return
  35. for ancestor in path:
  36. return root
  37. def __iter__(self):
  38. """Iterate through all items ever found or unioned by this structure."""
  39. return iter(self.parents)
  40. def union(self, *objects):
  41. """Find the sets containing the objects and merge them all."""
  42. roots = [self[x] for x in objects]
  43. heaviest = max([(self.weights[r],r) for r in roots])[1]
  44. for r in roots:
  45. if r != heaviest:
  46. self.weights[heaviest] += self.weights[r]
  47. self.parents[r] = heaviest
  48. """
  49. Various simple functions for graph input.
  50. Each function's input graph G should be represented in such a way that "for v in G" loops through the vertices, and "G[v]" produces a list of the neighbors of v; for instance, G may be a dictionary mapping each vertex to its neighbor set.
  51. D. Eppstein, April 2004.
  52. """
  53. def isUndirected(G):
  54. """Check that G represents a simple undirected graph."""
  55. for v in G:
  56. if v in G[v]:
  57. return False
  58. for w in G[v]:
  59. if v not in G[w]:
  60. return False
  61. return True
  62. def union(*graphs):
  63. """Return a graph having all edges from the argument graphs."""
  64. out = {}
  65. for G in graphs:
  66. for v in G:
  67. out.setdefault(v,set()).update(list(G[v]))
  68. return out
  69. Kruskal's algorithm for minimum spanning trees. D. Eppstein, April 2006.
  70. """
  71. def MinimumSpanningTree(G):
  72. """
  73. Return the minimum spanning tree of an undirected graph G.
  74. G should be represented in such a way that iter(G) lists its
  75. vertices, iter(G[u]) lists the neighbors of u, G[u][v] gives the
  76. length of edge u,v, and G[u][v] should always equal G[v][u].
  77. The tree is returned as a list of edges.
  78. """
  79. if not isUndirected(G):
  80. raise ValueError("MinimumSpanningTree: input is not undirected")
  81. for u in G:
  82. for v in G[u]:
  83. if G[u][v] != G[v][u]:
  84. raise ValueError("MinimumSpanningTree: asymmetric weights")
  85. # Kruskal's algorithm: sort edges by weight, and add them one at a time.
  86. # We use Kruskal's algorithm, first because it is very simple to
  87. # implement once UnionFind exists, and second, because the only slow
  88. # part (the sort) is sped up by being built in to Python.
  89. subtrees = UnionFind()
  90. tree = []
  91. for W,u,v in sorted((G[u][v],u,v) for u in G for v in G[u]):
  92. if subtrees[u] != subtrees[v]:
  93. tree.append((u,v))
  94. subtrees.union(u,v)
  95. return tree
  96. # If run standalone, perform unit tests
  97. class MSTTest(unittest.TestCase):
  98. def testMST(self):
  99. """Check that MinimumSpanningTree returns the correct answer."""
  100. G = {0:{1:11,2:13,3:12},1:{0:11,3:14},2:{0:13,3:10},3:{0:12,1:14,2:10}}
  101. T = [(2,3),(0,1),(0,3)]
  102. for e,f in zip(MinimumSpanningTree(G),T):
  103. self.assertEqual(min(e),min(f))
  104. self.assertEqual(max(e),max(f))
  105. if __name__ == "__main__":