你是紅軍指揮官,在一場軍事演習中,你的部分軍隊被藍軍包圍了。藍軍包圍的方式如下
在上圖中,每個頂點表示藍軍的部隊,頂點中數字表示藍軍在此處的人數(千人),兩點間的邊表示藍軍兩個部隊間形成的火線,火線構成的圈即是一道包圍,一條火線的戰鬥力為其相連兩個部隊的人數和,也是你要進攻這條火線所要消耗的兵力。你可以同時進攻藍軍的多條火線,請以成本最低的方式打破藍軍包圍,營救被包圍的部隊,計算出所需要消耗的兵力數(千人)
每個測試例輸出一行,是乙個正整數:打破包圍營救戰友的最小消耗兵力。
使用並查集優化的kruskal演算法實現
#!/usr/bin/env python3
#rescue.py
#fumiama 20201115
class
unionfindset
(object):
def__init__
(self, nodes)
: self.fathermap =
self.setnummap =
for node in nodes:
self.fathermap[node]
= node
self.setnummap[node]=1
deffindfather
(self, node)
: father = self.fathermap[node]
if(node != father)
: father = self.findfather(father)
self.fathermap[node]
= father
return father
defissameset
(self, a, b)
:return self.findfather(a)
== self.findfather(b)
defunion
(self, a, b)
:if a is
none
or b is
none
:return
afather = self.findfather(a)
bfather = self.findfather(b)
if(afather != bfather)
: anum = self.setnummap[afather]
bnum = self.setnummap[bfather]
if(anum <= bnum)
: self.fathermap[afather]
= bfather
self.setnummap[bfather]
= anum + bnum
self.setnummap.pop(afather)
else
: self.fathermap[bfather]
= afather
self.setnummap[afather]
= anum + bnum
self.setnummap.pop(bfather)
class
node
(object):
def__init__
(self, name, size, links)
: self.name = name
self.size = size
self.links = links
def__repr__
(self)
:return
"(節點:"
+str
(self.name)
+", 大小:"
+str
(self.size)
+", 連線到:"
+str
(self.links)
+")"
class
graph
(object):
def__init__
(self)
: self.edges =
self.nodes =
set(
) self.sizes =
dict
(map
=int
) self._edgessets =
#識別重複邊
defaddnode
(self, node)
: self.nodes.add(node)
self.sizes[node.name]
= node.size
defcalcedgeweights
(self)
:for node in self.nodes:
for link in node.links:
edge =(-
(node.size + self.sizes[link]
), node.name, link)
#邊權為負構造大頂堆
sedge =
if sedge not
in self._edgessets:
defrescue
(self)
: forest = unionfindset(self.sizes.keys())
edges = self.edges.copy(
) cost =
0while edges:
if forest.issameset(edge[1]
, edge[2]
): cost -= edge[0]
else
: forest.union(edge[1]
, edge[2]
)return cost
def__repr__
(self)
:return
"圖資訊:\n邊: "
+str
(self.edges)
+"\n點: "
+str
(self.nodes)
if __name__ ==
'__main__'
: n =
int(
input()
) graph = graph(
)while n:
m =int(
input()
)while m:
no, size, edgecnt =
map(
int,
input()
.split())
links =
[int
(x)for x in
input()
.split()]
graph.addnode(node(no, size, links)
) m -=
1 graph.calcedgeweights(
)#print(graph)
mincost = graph.rescue(
)#print("最小兵力:", mincost)
print
(mincost)
n -=
1
最大生成樹
problem a 古老的羊皮卷 time limit 3 sec memory limit 128 mb description 奇奇,乙個響亮的名字在acm界.如今奇奇已經腰纏萬貫,飛黃騰達,日子過的是無比的滋潤.是什麼使他到了如此的地位?如果你要這麼問,奇奇會不假思索的告訴你 acm 是acm...
最大生成樹
include define pp make pair using namespace std typedef long long ll const int maxn 1e6 30 const int n 260000 const ll mod 1e9 7 const int inf 0x3f3f3...
最大生成樹
最大生成樹演算法和最小生成樹演算法幾乎一樣,只需要我們把最小生成樹演算法進行一點點改變即可。當你用krushal演算法求最小生成樹的時候,每一次選取的邊都是最小的邊,然後再去判斷這條邊是否可以加入最小生成樹 那麼當你每一次選擇的邊是最大的邊,然後再去判斷這條邊是否可以加入,那麼這就是最大生成樹的求取...