有一个M行N列的点阵,相邻两点可以相连。一条纵向的连线花费一个单位,一条横向的连线花 费两个单位。某些点之间已经有连线了,试问至少还需要花费多少个单位才能使所有的点全部连通。 Input 第一行输入两个正整数m和n。 以下若干行每行四个正整数21,y1,22,y2,表示第1行第y1列的点和第c2行第y2列的点已 经有连线。输入保证|c1-22|+|y1-y2|=1。 Output 输出使得连通所有点还需要的最小花费。
这个问题可以看作是一个加权图的最小生成树(Minimum Spanning Tree, MST)问题。我们需要使用Kruskal算法或Prim算法来解决这个问题。以下是使用Kruskal算法的解决方案。
以下是Python代码实现:
class UnionFind:
def __init__(self, size):
self.parent = list(range(size))
self.rank = [1] * size
def find(self, p):
if self.parent[p] != p:
self.parent[p] = self.find(self.parent[p])
return self.parent[p]
def union(self, p, q):
rootP = self.find(p)
rootQ = self.find(q)
if rootP != rootQ:
if self.rank[rootP] > self.rank[rootQ]:
self.parent[rootQ] = rootP
elif self.rank[rootP] < self.rank[rootQ]:
self.parent[rootP] = rootQ
else:
self.parent[rootQ] = rootP
self.rank[rootP] += 1
return True
return False
def min_cost_to_connect_all_points(m, n, existing_edges):
edges = []
uf = UnionFind(m * n)
# Add all possible edges
for i in range(m):
for j in range(n):
if i < m - 1:
edges.append((1, i * n + j, (i + 1) * n + j)) # vertical edge
if j < n - 1:
edges.append((2, i * n + j, i * n + j + 1)) # horizontal edge
# Mark existing edges
for c1, y1, c2, y2 in existing_edges:
if c1 == c2:
uf.union((c1 - 1) * n + (y1 - 1), (c2 - 1) * n + (y2 - 1))
else:
uf.union((c1 - 1) * n + (y1 - 1), (c2 - 1) * n + (y2 - 1))
# Sort edges by cost
edges.sort()
# Kruskal's algorithm to find MST
total_cost = 0
for cost, u, v in edges:
if uf.union(u, v):
total_cost += cost
return total_cost
# Read input
import sys
input = sys.stdin.read
data = input().split()
m = int(data[0])
n = int(data[1])
existing_edges = []
index = 2
while index < len(data):
c1 = int(data[index])
y1 = int(data[index + 1])
c2 = int(data[index + 2])
y2 = int(data[index + 3])
existing_edges.append((c1, y1, c2, y2))
index += 4
# Calculate the minimum cost
result = min_cost_to_connect_all_points(m, n, existing_edges)
print(result)
这个解决方案能够有效地计算出使所有点连通所需的最