運輸計畫 二分答案 樹上差分

2022-05-20 22:55:46 字數 1275 閱讀 7564

p2680 運輸計畫

附贈樣例圖:

首先容易想到二分答案,將求解問題轉換為判定,並且注意到答案顯然具有單調性。

然後我們考慮如何快速判定。先預處理出所有計畫路徑長(\(dis[i]\)表示根節點到節點\(i\)的距離,\(dis[u]+dis[v]-2\times dis[lca(u,v)]\)即為樹上\(u,v\)路徑長),對於那些路徑長已經超過二分距離\(x\)的計畫,我們必須能找到一條公共邊 且 刪去此邊後最長距離小於等於\(x\),否則無法滿足\(x\),判定當前\(x\)為假。

之後考慮如何快速求得公共邊,使用樹上差分,具體將邊塞入較深的點,cnt[u]+=1,cnt[v]+=1,cnt[lca(u,v)]-=2,最後再回溯時求樹上字首和即可求得邊覆蓋次數。一條邊是公共邊當且僅當覆蓋次數為路徑個數。

綜上,判定時找到超過\(x\)的路徑的最長的公共邊後,判斷刪去後是否能滿足\(x\)即可

其實不是很毒瘤,相比於瘟疫控制

#include #include #include #define maxn 300003

#define log 20

using namespace std;

inline int read()

int head[maxn],nxt[maxn*2],vv[maxn*2],ww[maxn*2],tot;

inline void add_edge(int u, int v, int w)

int dis[maxn];

int dep[maxn],f[maxn][log];

void dfs(int u, int fa)

int n,m;

struct noda[maxn];

int d[maxn],dmx;

int cnt[maxn];

void calc(int u, int fa, const int num, int &res)

}bool check(int x)

if(num==0) return x>=dmx;

calc(1, 0, num, res);

if(dmx-res<=x) return 1;

return 0;

}int main()

printf("%d", ans);

return 0;

}

P2680 運輸計畫 二分 樹上差分

又咕咕了幾天 qwq 我們先將原問題轉化為 log 2n 個判定問題 如何 ck x 把所有 x 的路徑在樹上標記 邊差分 然後找到被所有 x 路徑覆蓋的點 邊轉點,邊權下放點權 嘗試把這個點的權值改為零,檢查最長路徑的時間是否 leq x 若存在這樣的點,return true 否則 return...

P2680 運輸計畫(二分 樹上差分)

鏈結分析 二分 樹上差分。首先可以二分乙個答案,那麼所有比這個答案大的路徑,都需要減去些東西才可以滿足這個答案。那麼減去的這條邊一定在所有的路徑的交集上。那麼如果求快速的求出這個交集並判斷呢,樹剖可以,把所有大於的路徑都標記一下,然後判斷,複雜度太大了。於是用到了樹上差分,get新技能。在兩個端點出...

Luogu P2680運輸計畫(樹上差分 二分)

題目鏈結 總體思路 怎麼說呢 是個暴力吧 首先用倍增預處理出每條路徑的長度。然後按長度把路徑排序。然後二分答案。對於當前答案mid檢驗,怎麼檢驗呢?首先差分把所有長度比mid大的鏈上除了lca之外的所有點權 1。dfs求出每個點的點權,順便記下有多少點是被所有路徑經過的。對於這些點,如果有乙個點使得...