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求出每個點的點權,順便記下有多少點是被所有路徑經過的。對於這些點,如果有乙個點使得...