最小生成樹 Tree

2022-05-25 03:21:10 字數 1713 閱讀 6611

參考資料:

description

給你乙個無向帶權連通圖,每條邊是黑色或白色。讓你求一棵最小權的恰好有need條白色邊的生成樹。

題目保證有解。

input

第一行v,e,need分別表示點數,邊數和需要的白色邊數。

接下來e行

每行s,t,c,col表示這邊的端點(點從0開始標號),邊權,顏色(0白色1黑色)。

output

一行表示所求生成樹的邊權和。

sample input

2 2 1

0 1 1 1

0 1 2 0

sample output

2hint

資料規模和約定

0:v<=10

1,2,3:v<=15

0,..,19:v<=50000,e<=100000

所有資料邊權為[1,100]中的正整數。

---------------------

題解摘抄:

顯然可以發現隨著白邊權值的增大。最小生成樹中白邊的個數不增。

然後根據這個性質我們就可以二分乙個值,然後每次給白邊加上這個值。看一下最小生成樹中白邊的個數。

最後答案再把它減去。

看起來思路非常簡單,但是有乙個很重要的細節。

如果在你的二分過程中如果給白邊加上mid,你得到的白邊數比need大。

給白邊加上mid+1,你得到的白邊比need小。

這種情況看似沒法處理。

但是考慮一下克魯斯卡爾的加邊順序。

可以發現如果出現這種情況,一定是有很多相等的白邊和黑邊。因為資料保證合法。

所以我們可以把一些白邊替換成黑邊。

所以我們要在白邊數》=need的時候跟新答案。

具體用ans=ans-mid*need;即可。

#includeusing

namespace

std;

struct

nodea[

1100000

];int pre[6000000

];int v,e,need,s[6000000],t[6000000],c[6000000],col[6000000],m=0

;int find(int x)

bool

cmp(node a,node b)

intans,tot;

int kruskal(int

mid)

}stable_sort(a+1,a+e+1

,cmp);

for(int i=0;i<=v+1;i++) pre[i]=i;//

注意點int cnt=0

; tot=0

;

for(int i=1;i<=e;i++)

if(cnt==v-1) break

; }

}return

num;

}int

main()

int l=-155555,r=155555;//

注意點三

while(l<=r)

else r=mid-1

; }

cout

}

次小生成樹Tree

小c最近學了很多最小生成樹的演算法,prim演算法 kurskal演算法 消圈演算法等等。正當小c洋洋得意之時,小p又來潑小c冷水了。小p說,讓小c求出乙個無向圖的次小生成樹,而且這個次小生成樹還得是嚴格次小的,也就是說 如果最小生成樹選擇的邊集是em,嚴格次小生成樹選擇的邊集是es,那麼需要滿足 ...

最小生成樹 次小生成樹

一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 1.兩點之間的路徑是唯一的。2.邊數等於點數減一。3.連線任意兩點都會生成乙個環。對於乙個無向聯通圖g的子圖,如果它包含g的所有點,則它被稱為g的生成樹,而各邊權和最小的生成樹則被稱...

次小生成樹 Tree(倍增)

時間限制 1000 ms 記憶體限制 524288 kb 小 c 最近學了很多最小生成樹的演算法,prim 演算法 kurskal 演算法 消圈演算法等等。正當小 c 洋洋得意之時,小 p 又來潑小 c 冷水了。小 p 說,讓小 c 求出乙個無向圖的次小生成樹,而且這個次小生成樹還得是嚴格次小的,也...