傳送門
考慮樹上亂搞
首先這是滿足二分性質的,如果在某個時間可以完成工作那麼比他更長的時間肯定也能完成工作
然後考慮二分,設當前答案為$mid$,如果有一條鏈的長度大於$mid$,那麼這條鏈上必須得刪去一條邊。我們可以貪心的刪去所有可以刪去的邊中最長的,然後看看最長邊減去刪去的邊是否小於等於$mid$,如果成立說明可行
然後考慮怎麼solve,我們可以用樹上差分,就是對於每個點把它看做他父親到他的邊,每個點記錄乙個$s$,然後對於一條鏈,兩個端點++,lca-=2。如果有乙個點的$s$等於大於$mid$的鏈的條數,說明它被所有的鏈給覆蓋,然後求乙個最大值就好了
然後每一條鏈的lca都要求出來……實際上直接每一條都$o(logn)$求出來也沒關係……不過**裡用的是tarjan離線求的,所以複雜度是$o(n+m)$
總複雜度是$o(nlogn)$(複雜度並沒有降……直接樹剖求lca可能更省力啊……)
1//minamoto
2 #include3 #include4 #include5
using
namespace
std;
6#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?eof:*p1++)
7char buf[1
<<21],*p1=buf,*p2=buf;
8 templateinline bool cmax(t&a,const t&b)
9 inline int
read()
19const
int n=3e5+5;20
int head[n],next[n<<1],ver[n<<1],edge[n<<1
],tot;
21int hq[n<<1],nq[n<<1],vq[n<<1
],tq;
22int
dis[n],a[n],fa[n],s[n],vis[n];
23int
n,mx,ans,res,num,m;
24struct
node
27 node(int u,int v,int len,int
lca):u(u),v(v),len(len),lca(lca){}
28 inline void solve()
29}q[n];
30 inline void add(int u,int v,int
e)33 inline void addq(int u,int
v)36
int find(int x)
37void dfs(int u,int
fa)43}44
if(s[u]==num) cmax(res,a[u]);45}
46bool check(int
x)53 dfs(1,0
);54
return mx-res<=x;55}
56void tarjan(int u,int
ff)67
for(int i=hq[u];i;i=nq[i])74}
75}76int
main()
91 printf("
%d\n
",ans);
92return0;
93 }
洛谷P2680 運輸計畫 樹上差分
題目 久違地1a了好高興啊!首先,要最大值最小,很容易想到二分 判斷當前的 mid 是否可行,需要看看有沒有去掉一條邊使滿足的方案 這就需要樹上差分來找出每條邊被幾個超過 mid 的路線覆蓋 若有一條邊正好被所有超過 mid 的路線覆蓋,且去掉它之後最大的路線也能滿足,就是可行的。如下 includ...
洛谷 P2680 運輸計畫
公元 2044 年,人類進入了宇宙紀元。l 國有 n 個星球,還有 n 1 條雙向航道,每條航道建立在兩個星球之間,這 n 1 條航道連通了 l 國的所有星球。小 p 掌管一家物流公司,該公司有很多個運輸計畫,每個運輸計畫形如 有一艘物 流飛船需要從 ui 號星球沿最快的宇航路徑飛行到 vi 號星球...
P2680 運輸計畫 二分 樹上差分
又咕咕了幾天 qwq 我們先將原問題轉化為 log 2n 個判定問題 如何 ck x 把所有 x 的路徑在樹上標記 邊差分 然後找到被所有 x 路徑覆蓋的點 邊轉點,邊權下放點權 嘗試把這個點的權值改為零,檢查最長路徑的時間是否 leq x 若存在這樣的點,return true 否則 return...