加超級源點的Kruskal演算法

2021-10-04 19:03:04 字數 1482 閱讀 5717

東東在老家農村無聊,想種田。農田有 n 塊,編號從 1~n。種田要灌氵

眾所周知東東是乙個魔法師,他可以消耗一定的 mp 在一塊田上施展魔法,使得黃河之水天上來。他也可以消耗一定的 mp 在兩塊田的渠上建立傳送門,使得這塊田引用那塊有水的田的水。 (1<=n<=3e2)

黃河之水天上來的消耗是 wi,i 是農田編號 (1<=wi<=1e5)

建立傳送門的消耗是 pij,i、j 是農田編號 (1<= pij <=1e5, pij = pji, pii =0)

東東為所有的田灌氵的最小消耗

第1行:乙個數n

第2行到第n+1行:數wi

第n+2行到第2n+1行:矩陣即pij矩陣

東東最小消耗的mp值

input45

4430 2 2 2

2 0 3 3

2 3 0 4

2 3 4 0

output

9

首先依然是對題目的理解,假如沒有「天上來」的操作,那麼就是乙個簡單的最小生成樹問題,使用kruskal演算法就可以求解。

但是此題並不是那麼簡單,黃河之水可以天上來,那麼每塊田就多出了乙個來水的渠道。既然如此,可以把黃河水看成乙個新的節點,然後對所有的點使用kruskal演算法求解即可。

kruskal演算法:將所有的邊按照從小到大的順序排序,依次取出最小的邊,判斷是否可以和已選出的邊形成迴路(利用並查集),若不會則選擇該邊,並將該邊兩個端點所在集合合併。共找出n-1條邊即可。

#include

#include

#include

using

namespace std;

const

int maxn=

310;

//田個數的最大值

const

int maxm=

90000

;//邊個樹的最大值

struct edge

edges[maxm]

;int tot=0;

//邊的數目

bool

cmp(edge x,edge y)

int par[maxn]

,rnk[maxn]

;void

init

(int n)

intfind

(int x)

bool

unite

(int x,

int y)

intmain()

for(

int i=

1;i<=n;i++)}

}sort

(edges,edges+tot,cmp)

;int start=0;

//邊集種選的邊

int mp=0;

//消耗的法力值

for(

int i=

0;i) cout

}

M 昂貴的聘禮 超級源點加dij

本菜雞還是太菜了,看了半天別人的題解發現理解錯題目意思了,題目的等級是這樣規定的如果你的等級是x,最大差值k,那麼你可以交易的人的等級就在 x k,x k 之間,其他等級都不可以,然後因為你沒有等級限制,那麼就特別難搞,我們就列舉假設和我們交換的人的最低等級,但是最低等級 m要包含酋長的等級所以最低...

poj1364(注意超級源點的選擇)

題目大意 已知乙個序列a 1 a 2 a n 給出它的若干子串行以及對該子串行的 約束條件,例如a si a si 1 a si 2 a si ni 且a si a si 1 a si 2 a si ni or ki。求是否存在滿足以上m個要求的數列。是 則輸出 lamentable kingdom...

POJ 1062 昂貴的聘禮 最短路 超級源點

年輕的探險家來到了乙個印第安部落裡。在那裡他和酋長的女兒相愛了,於是便向酋長去求親。酋長要他用10000個金幣作為聘禮才答應把女兒嫁給他。探險家拿不出這麼多金幣,便請求酋長降低要求。酋長說 嗯,如果你能夠替我弄到大祭司的皮襖,我可以只要8000金幣。如果你能夠弄來他的水晶球,那麼只要5000金幣就行...