bzoj2654 最小生成樹 二分 tree

2021-08-13 13:14:37 字數 1612 閱讀 4092

description

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

input

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

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

output

一行表示所求生成樹的邊權和。 v<=50000,e<=100000,所有資料邊權為[1,100]中的正整數。

sample input

2 2 1

0 1 1 1

0 1 2 0

sample output

題解

神題吶不會啊只能膜題解了。。

如果直接對原樹進行kruskal的話,求出來的白邊可能<need也可能>need的對不

那麼怎麼人為控制白邊在樹里的數目同時保證黑邊選擇最小吶?

還是最小生成樹,只不過我們二分乙個值mid,每次check的時候每條白邊加上這個mid值,這樣可以保證白邊在生成樹里一定是單調不下降或者單調不上公升的,而這個時候的黑邊同樣***一定是最小的。

跑kruskal的時候判一下白邊的邊數,如果出來的邊數》=need就是正確狀態,那麼樹里的白邊就需要減小,這時候mid往大的二分

小於need的情況就往小的二分

答案繼承的時候需要減去mid*need這麼多,因為白邊至少都多了這麼多的權嘛

乙個特別的地方:題裡可能有權相等的黑白邊,這樣kruskal排序的時候黑白邊順序是不定的。那這樣跑出來的邊數就可能小於need而wa掉。所以我們排序的時候當邊權相等的時候再按顏色排,白色在前

#include

#include

#include

#include

#include

using

namespace

std;

struct node

a[211000],e[211000];

int fa[111000];

int findfa(int x)

int n,m,nd,cnt;

bool cmp(node n1,node n2)

for(int i=1;i<=n;i++)fa[i]=i;

sort(e+1,e+1+m,cmp);

int tmp=n,op=0;cnt=0;

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

}if(op>=nd)return

true;

else

return

false;

}int main()

int l=-150,r=150,ans;

while(l<=r)

else r=mid-1;

}printf("%d\n",ans);

return

0;}

bzoj2654 二分 最小生成樹

題目戳這裡 我們知道對於乙個最小生成樹而言,它的白邊權值越大,那麼生成樹中的白邊個數越少,反之亦然。所以我們每次二分乙個值,給白邊加上它,在做最小生成樹判斷是否大於所需要的,然後就可以二分來搞了。include include include include define n 100005 usin...

bzoj2654 二分答案 最小生成樹

2654 tree time limit 30 sec memory limit 512 mb submit 1975 solved 810 submit status discuss description 給你乙個無向帶權連通圖,每條邊是黑色或白色。讓你求一棵最小權的恰好有need條白色邊的生成...

bzoj2654 二分 最小生成樹 tree

題目傳送門 description 給你乙個無向帶權連通圖,每條邊是黑色或白色。讓你求一棵最小權的恰好有need條白色邊的生成樹。題目保證有解。input 第一行v,e,need分別表示點數,邊數和需要的白色邊數。接下來e行,每行s,t,c,col表示這邊的端點 點從0開始標號 邊權,顏色 0白色1...