我們對每條邊\(i\)單獨考慮,那麼設\(v_i\)為這條邊的長度,經過它的路徑長度集合為\(s\),未經過它的路徑長度集合為\(t\)
\[ans_i=\max
\begin
s_-v_i \\
t_\end \\
ans=\min ans_i
\]對於\(s_\),我們直接對於一條長度為\(l\)的路徑,該路徑上的邊都對\(l\)取\(\max\),用樹鏈剖分很容易處理
對於\(t_\),對於一條長度為\(l\)的路徑,不在該路徑上的邊都對\(l\)取\(\max\),也就是計算\(s_\)時邊的補集,我們可以記錄樹剖時覆蓋了哪些段,剩餘的段就是\(t_\)應當覆蓋的了,由於樹剖頂多\(\log n\)段,\(t_\)覆蓋的段頂多比\(s_\)覆蓋的段多乙個
計算路徑長度\(l\),用了帶按秩合併優化的\(tarjan\)求\(lca\)
時間複雜度:\(o(n \log^2 n)\)
掛點\(1.\)線段樹忘開四倍空間。。。
掛點\(2.\)一開始\(t\)了,結果發現是它的鍋
#define rmin(x,y) ((xy)?x:y)
在下面的**的線段樹中,由於\(define\),需要先線段樹搜尋一次,與\(y\)比較,然後返回值時再搜尋一次,時間**
經驗:下次寫什麼函式之類的再也不用\(define\)了\(qaq\)
錯誤**:
#define rmin(x,y) ((xy)?x:y)
#define ls (p << 1)
#define rs ((p << 1) | 1)
#define lc ls,l,mid
#define rc rs,mid+1,r
struct segment_tree
int mid=(l+r) >> 1;
if (y<=mid)
modify(lc,x,y,z); else
if (x>mid)
modify(rc,x,y,z); else
}int query(int p,int l,int r,int x)
}t1,t2;
完整\(ac\)**
\(code:\)
#include#include#include#include#define n 300005
using namespace std;
int n,m,x,y,z,tot=0,fr[n],nxt[n << 1],d1[n << 1],d2[n << 1];
int cnt=0,f[n],dep[n],son[n],sz[n],dfn[n],t[n],len[n];
int ans,ft[n],rf[n],rz[n],rg[n],lca[n];
struct node
bool operator < (const node &b) const
return s;
}void write(int x)
void add(int x,int y,int z)
int getf(int x)
void dfs1(int u)
int fu=getf(u);
int fv=getf(v);
if (rz[fv]<=rz[fu])
else
}for (vector:: iterator it=e[u].begin();it!=e[u].end();++it)
if (rf[it->x])
lca[it->y]=rg[getf(it->x)];
}void dfs2(int u,int tt)
}#define ls (p << 1)
#define rs ((p << 1) | 1)
#define lc ls,l,mid
#define rc rs,mid+1,r
struct segment_tree
int mid=(l+r) >> 1;
if (y<=mid)
modify(lc,x,y,z); else
if (x>mid)
modify(rc,x,y,z); else
}int query(int p,int l,int r,int x)
}t1,t2;
void achange(int x,int y,int z)
sort(g+1,g+g0+1);
int o=1;
for (int i=1;i<=g0;o=g[i].y+1,i++)
if (o<=n)
t2.modify(1,1,n,o,n,z);
}int main()
for (int i=1;i<=m;i++)
q[i].x=read(),q[i].y=read(),e[q[i].x].push_back(node(q[i].y,i)),e[q[i].y].push_back(node(q[i].x,i));
dfs1(1);
dfs2(1,1);
for (int i=1;i<=m;i++)
ans=1000000007;
for (int i=2;i<=n;i++)
write(ans),putchar('\n');
return 0;
}
luogu2680 運輸計畫
很明顯,由於是求最長路的最小值,我們可以使用二分求解.我們二分乙個長度 mid 將所有使得 dis u,v 大於 mid 的點對 u,v 找出,設總共有 m 條這樣的邊,那麼我們需要改變的改變邊一定是被這 m 條邊都經過的邊,所以我們只需要找到滿足這個要求的長度最大的改變邊使得這 m 條邊中最長的一...
luogu2680 運輸計畫
首先二分列舉答案t,考慮刪去的邊應滿足的條件 所有大於 t的鏈全部經過且長度不小於最長鏈 t,第二個條件很好判斷,考慮第乙個條件。先考慮有祖先 後代關係的鏈,用如果把這條鏈到 1看成乙個序列,那麼差分一下再 dfs一遍就可以對這條鏈上每乙個點打上標記。然後沒有祖先 後代關係的鏈,同樣可以分解成兩條鏈...
題解 LuoGu2680 運輸計畫
原題傳送門 去年覺得是道難題,現在覺得這著實是道大水題 題意 一棵樹,給出幾條路徑 從點x到點y 可以使一條邊長度變為0,使得路徑長度最大值最小 思路 就搞定了 接著想如何實現 總結 noip的題目還是很可以的,演算法 思維難度不高,應用性還是比較強的 用到了許多小演算法 lca,二分,樹上差分 c...