參考資料:
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;即可。
#includeusingnamespace
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 求出乙個無向圖的次小生成樹,而且這個次小生成樹還得是嚴格次小的,也...