BZOJ2654 tree 生成樹 二分

2022-08-16 13:57:15 字數 1283 閱讀 3134

題目鏈結

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

題目保證有解,輸出最小權值。

其中每條邊權在\([1,100]\)範圍內。

首先有乙個比較明顯的想法:

用kruskal跑出乙個最小生成樹,然後再不斷往其中加邊調整白色邊的數量,用lct維護圈內最大異色邊。

好吧,這種極其複雜的演算法可以被以下例子卡掉。

假如隨便跑的乙個最小生成樹是下圖:

(邊左邊為顏色,右邊為邊權)

再考慮加入以下邊:

假如需要一條白邊,並且按從小到大的順序選白邊,那麼就會先選 6-7 這條邊,刪 5-8 這條邊,這樣做會產生 1 的貢獻。但如果我們選 2-3 這條邊,刪 1-4 這條邊,那麼對答案的貢獻就是 0,明顯更優。

考慮乙個正常的演算法:

我們考慮給每條白邊附加乙個權值\(w\),使得白邊邊權由\(val\)變為\(val+w\),然後再跑一遍最小生成樹。

可以發現,當\(w\)越大時,白邊數量越少,即呈單調性。

於是考慮二分\(w\)的值,每次二分根據當前最小生成樹能得到的最小或最大白邊數與\(need\)的大小關係check就行。

正確性小記:

細節:tle小記:

#include#includeusing namespace std;

const int maxn=100005;

int n,m,ned,fa[maxn];long long ans;

struct edges[maxn],tmp[maxn];

bool cmp(edge a,edge b)

int find(int x)

void turn(double p)sort(s+1,s+m+1,cmp);

}int get()

return ret;

}bool check(int p)

int main()

turn(l);get();ans=0;

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

if(s[i].vis)ans+=tmp[s[i].id].z;

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

}

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不...