BZOJ 2654 tree 最小生成樹 二分

2021-08-09 09:06:01 字數 1603 閱讀 9318

time limit: 30 sec memory limit: 512 mb

submit: 2344 solved: 975

[submit][status][discuss]

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

題目保證有解。

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

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

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

v<=50000,e<=100000,所有資料邊權為[1,100]中的正整數。

2 2 1

0 1 1 1

0 1 2 0

原資料出錯,現已更新 by liutian,但未重測—2016.6.24

題解:

考試的前一天看了這道題,然而當時覺得太難了就沒有做,然後考到了:)

首先如果每條白邊的權值逐漸增大的話,那麼最小生成樹上白邊的數量肯定是單調不下降的。所以我們可以利用這個性質來二分乙個權值mid,然後將每條白邊都加上這個mid,再跑最小生成樹。如果最小生成樹上選取的白邊的數量》=need,那麼白邊的權值應該再大一點,反之。

最後就得到了乙個mid,使得所有白邊+mid之後,可以選取到》=need條白邊,但對於mid+1,就小於了need條白邊。這樣肯定可以證明有一些黑邊與白邊的權值一樣,因為資料保證有解,所以即使是大於的,也沒關係,可以選權值一樣的黑邊。

最後的答案就是我們得到這顆生成樹的權值和-mid*need(白邊增量)。

感性理解一下還是很正確的…

#include

#include

#include

using

namespace

std;

inline

int read()

while(ch>='0'&&ch<='9')

return x*f;

}const

int n = 100000 + 10;

const

int inf = 0x7f;

int n,m,need;

struct nodee[n];

bool

operator

< (node a,node b)

int aans=0;

bool check(int mid)

sort(e+1,e+m+1);int cnt=0,ans=0;

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

if(ans>=need) return

true;

return

false;

}int main()

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

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

int cnt=0;

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

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

while(l<=r)

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

return

0;}

BZOJ 2654 tree 二分 最小生成樹

給出一些邊,每個邊有乙個邊權和顏色。現在要求出最小邊權有need個白邊的生成樹。輸出這個邊權。在白邊上加乙個權值,這樣就可以人為的改變白邊出現在最小生成樹。這個東西顯然可以二分。之後取一下最小值就可以了。define crt secure no warnings include include in...

bzoj2654 tree 二分 最小生成樹

time limit 30 sec memory limit 512 mb submit status discuss 給你乙個無向帶權連通圖,每條邊是黑色或白色。讓你求一棵最小權的恰好有need條白色邊的生成樹。題目保證有解。第一行v,e,need分別表示點數,邊數和需要的白色邊數。接下來e行,每...

bzoj2654 tree(二分 最小生成樹)

我是超連結 一開始博主想要把黑白邊分開,然後sort,選擇前need小的白邊連起來,然後再連黑邊 但這個貪心是不對的,因為黑邊的大小不確定,如果目前選擇了較小的白邊,可能會選上更大的黑邊 問題的關鍵在於求出的最小生成樹不一定含有need條白邊 1 如果白邊 need條,我們需要 拖累 白邊,讓ta不...