营救 (通信网理论基础)
题目大意:
你是红军指挥官,在一场军事演习中,你的部分军队被蓝军包围了。蓝军包围的方式如下
在上图中,每个顶点表示蓝军的部队,顶点中数字表示蓝军在此处的人数(千人),两点间的边表示蓝军两个部队间形成的火线,火线构成的圈即是一道包围,一条火线的战斗力为其相连两个部队的人数和,也是你要进攻这条火线所要消耗的兵力。你可以同时进攻蓝军的多条火线,请以成本最低的方式打破蓝军包围,营救被包围的部队,计算出所需要消耗的兵力数(千人)
输入:
输入包含多个测试例。
第一行是一个整数n,表示测试测试例数量。
对每个测试例:
第一行是一个正整数m(2<m200),是蓝军部队数。
每个蓝军部队有两行:
一行3个正整数:i为部队编号(0im-1),ai为蓝军部队人数(千人)(1ai100),bi为与该部队能形成火线的部队数量(1bim-1)。
一行有bi个正整数,分别是与部队i形成火线的部队编号,数字间有空格。
至少有一个包围。
输出:
每个测试例输出一行,是一个正整数:打破包围营救战友的最小消耗兵力。
输入样例:
1
3
0 1 2
1 2
1 2 2
0 2
2 3 2
0 1
输出结果:
3
题目分析:形成一个最大生成树,剃掉的边即为所需破圈边。
import sys, time
from heapq import heappop, heappush
edgeLinks = dict()
edgeWeights = []
edgeWeightsAbout = dict()
P = dict()
nodes = set()
count=0
sum=0
class UnionFind(): #数据结构建立
def __init__(self, nodes):
self.prior = {}
self.setNum = {}
for node in nodes:
self.prior[node] = node
self.setNum[node] = 1
def findP(self, node): #
prior = self.prior[node]
if (node != prior):
prior = self.findP(prior)
self.prior[node] = prior
return prior
def union(self, left, right): #维护功能
if left is None or right is None: return
aP = self.findP(left)
bP = self.findP(right)
if (aP != bP):
aNum = self.setNum[aP]
bNum = self.setNum[bP]
if (aNum <= bNum):
self.prior[aP] = bP
self.setNum[bP] = aNum + bNum
self.setNum.pop(aP)
else:
self.prior[bP] = aP
self.setNum[aP] = aNum + bNum
self.setNum.pop(bP)
def isSameSet(self, left, right): # 判断left和right两个集合是否相同
return self.findP(left) == self.findP(right)
def kruskalMST():
global edgeLinks, edgeWeights,count
forest = UnionFind(nodes)
count=0
while edgeWeights != []:
minWeight = heappop(edgeWeights)#把最小权重边弹出
if minWeight in edgeWeightsAbout.keys(): #判断是否存在该集合
minEdge = edgeWeightsAbout[minWeight].pop() #最小边弹出
a = minEdge.pop()#前后节点弹出
b = minEdge.pop()
if edgeWeightsAbout[minWeight] == []:
edgeWeightsAbout.pop(minWeight)
if not forest.isSameSet(a,b):
print("剩%c->%c"%(a,b))#拓展顺序打印
count=count-minWeight
forest.union(a,b)#调用union函数
# print(count)
t=int(input())
# print(type(t))
for item in range(t):
V = int(input())
if (V < 2 or V > 200):
sys.exit()
for item1 in range(V):
a, b, c = map(int, input().split())
nodes.add(str(a))
bi = int(b)
edge = []
edge = input().split()
# print(edge)
P.update({a: bi})
# print(P[0])
for item2 in range(c):
if str(a) not in edgeLinks:edgeLinks[str(a)] = set()
edgeLinks[str(a)].add(str(edge[item2]))
if a>int(edge[item2]):
if P[int(edge[item2])] != None:
t=P[a] + P[int(edge[item2])]
sum=sum+t
z=-t
if z not in edgeWeightsAbout.keys():
edgeWeightsAbout[z] = []
if {str(a), edge[item2]} not in edgeWeightsAbout[z]:
edgeWeightsAbout[z].append({str(a), edge[item2]})
# # edgeWeights.append(t)
if z not in edgeWeightsAbout.keys():edgeWeightsAbout[z] = []
if {str(a), str(edge[item2])} not in edgeWeightsAbout[z]:edgeWeightsAbout[z].append({str(a), str(edge[item2])})
heappush(edgeWeights, z)
# print(edgeWeights)
# print(edgeLinks)
# print(P)
# print(edgeLinks)
# print(edgeWeights)
# print(edgeWeightsAbout)
kruskalMST()
print(sum-count)
count=0
sum=0
输入数据和结果如下: