营救问题(python实现)

营救 (通信网理论基础)

题目大意:

你是红军指挥官,在一场军事演习中,你的部分军队被蓝军包围了。蓝军包围的方式如下
营救问题(python实现)
在上图中,每个顶点表示蓝军的部队,顶点中数字表示蓝军在此处的人数(千人),两点间的边表示蓝军两个部队间形成的火线,火线构成的圈即是一道包围,一条火线的战斗力为其相连两个部队的人数和,也是你要进攻这条火线所要消耗的兵力。你可以同时进攻蓝军的多条火线,请以成本最低的方式打破蓝军包围,营救被包围的部队,计算出所需要消耗的兵力数(千人)
营救问题(python实现)
输入:
输入包含多个测试例。
第一行是一个整数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
营救问题(python实现)
输出结果:
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
    

输入数据和结果如下:
营救问题(python实现)

上一篇:十二月组队学习之——目标检测Task03:化劲儿-损失函数设计


下一篇:对存储在带头结点的双向链表中的记录利用双向冒泡排序法对其按升序排序