題目鏈結
給你乙個無向帶權連通圖,每條邊是黑色或白色,求一棵最小權的恰好有\(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不...