我是超連結
一開始博主想要把黑白邊分開,然後sort,選擇前need小的白邊連起來,然後再連黑邊
但這個貪心是不對的,因為黑邊的大小不確定,如果目前選擇了較小的白邊,可能會選上更大的黑邊
問題的關鍵在於求出的最小生成樹不一定含有need條白邊
1、如果白邊 > need條,我們需要「拖累」白邊,讓ta不要加進去那麼多,你光拖白邊a,不拖白邊b就很不公平啊,所以要拖累就把所有的白邊全都拖累上
2、如果白邊 < need條,我們需要「幫助」這些白邊,讓ta加進去的更多一些,那就給ta們全都減去乙個值
我們到底是幫助還是拖累呢?具體幫多少呢?我們可以運用二分!
你可以發現這是單調的:你加入的值越多,可以加入的白邊就越少;反之亦然
那就走起?最後的答案就是 sum-你新增的總值
下面是一些小細節:
當有一種情況,mid+1加入的白邊少1,mid加入的白邊多1,這要怎麼辦呢?這樣的情況只會出現於一些白邊和黑邊的權值相等,我們在排序的時候,權值相等的白邊在先就ok啦
以下為博主口胡,即使不注意這個,你依然可以過這道題
但你的程式不一定是對的,試一下(卡掉學姐的)這組資料
3 3 1
0 1 4 1
0 2 2 0
1 2 2 0
ans=6
乙個小問題:你的ans值什麼時候修改呢?我們說你不能對於ans取min值(why?)
如果你把這個語句(ans=min(ans,sum-need*mid))放在[選的白邊小於need]的後面,你就不怕一上來白邊就小於mid,選了一棵正常的最小生成樹,以後的權值肯定不會被修改
如果你把這個語句放在[選的白邊大於need]的後面,你就不怕一上來白邊大於mid,就同上了(hack了學姐。。。)
事實上可以證明當我們限定白邊的數量一定的時候,答案也是唯一的
可以避免這個問題:只有在白點相等的時候再修改ans值
但是這樣的答案是錯的?
為什麼呢?因為這道題的題目是錯的,ta其實想讓你求讓你求一棵最小權的至少有need條白色邊的生成樹。
發現這個問題之後,以上就全部是博主的自我揣測了
#include
#include
#include
#define inf 1e9
using namespace std;
struct hhe[100005],b[100005];
int f[50005],n,m,ne,sum;
int cmp(hh a,hh b)
int check(int mid)
sort(b+1,b+m+1,cmp);
for (i=1;i<=m;i++)
if (tot==n-1) break;
}return size;
}int main()
printf("%d",ans);
}
BZOJ 2654 tree 二分答案
根據mst演算法的性質,每次選權值最小的邊,所以我們可以給白邊加上或減去乙個權值k 令白邊被少選或者多選,二分k即可。ps 機房裡大神突然討論起乙個好像很有道理但實際上並沒用什麼卵用的問題 如果當某乙個權值有很多條白邊和黑邊,如果加上乙個k的時候只選到了need 1條邊,而加上k 1的時候會選到ne...
BZOJ2654 tree 生成樹 二分
題目鏈結 給你乙個無向帶權連通圖,每條邊是黑色或白色,求一棵最小權的恰好有 need 條白色邊的生成樹。題目保證有解,輸出最小權值。其中每條邊權在 1,100 範圍內。首先有乙個比較明顯的想法 用kruskal跑出乙個最小生成樹,然後再不斷往其中加邊調整白色邊的數量,用lct維護圈內最大異色邊。好吧...
BZOJ 2654 tree 二分 最小生成樹
給出一些邊,每個邊有乙個邊權和顏色。現在要求出最小邊權有need個白邊的生成樹。輸出這個邊權。在白邊上加乙個權值,這樣就可以人為的改變白邊出現在最小生成樹。這個東西顯然可以二分。之後取一下最小值就可以了。define crt secure no warnings include include in...