題目大意:給定一棵樹,再給定k條路徑,求把一條邊權改為0後使這些路徑的最長距離最小。
題解:首先可以想到用二分(誰說想得到的!!!),在列舉出來的長度mid上找到長度大於mid的路徑,檢查把這些路徑中最長的公共邊置為0之後的最長鏈。若長度還是大於mid,則該長度不合法。實際編碼中,可以用樹上差分來解決邊覆蓋的問題。
我用倍增寫的lca,如果換成樹鏈剖分或者tarjan,rmq什麼的會更快~
#include
#include
#include
using
namespace std;
const
int maxn =
300001
;int n, m, mid;
int fir[maxn]
, nxt[maxn <<1]
, to[maxn <<1]
, len[maxn <<1]
, cnt;
int dep[maxn]
, dis[maxn]
, fa[20]
[maxn]
;int tag[maxn]
, size[maxn]
, d1, num;
struct edgee[maxn]
;inline
intread()
while
(ch >=
'0'&& ch <=
'9')
return k * f;
}inline
void
add_edge
(int a,
int b,
int l)
void
dfs1
(int u,
int f)
intlca
(int x,
int y)
inline
bool
cmp(edge a, edge b)
void
dfs2
(int u,
int f)
if(u !=
1&& size[u]
== num)
}bool
check()
// printf("l = %d, r = %d\n", l, r);
num = m - l +1;
// printf("mid = %d, num = %d\n", mid, num);
memset
(tag,0,
sizeof
(tag));
//tag一定要清零!!!
for(
int i = l; i <= m; i++
) d1 =0;
dfs2(1
,-1)
;// printf("d1 = %d\n", d1);
if(e[m]
.len - d1 > mid)
return
false
;return
true;}
intmain()
dep[0]
=-1;
dfs1(1
,0);
int l, r =0;
for(
int i =
1; i <= m; i++
) l = r - maxlen;
// sort(e + 1, e + m + 1, cmp);
// for(int i = 1; i <= m; i++)
// printf("%d ", e[i].len);
// printf("\n");
while
(l < r)
printf
("%d"
, l)
;return0;
}
佔坑:在luogu上過了,本校oj上t了乙個點,明天再寫tarjan吧。。 NOIp 2015 運輸計畫 LCA
問題大意 有n個星球與n 1條雙向邊,每條邊有時間ti,有m個從vi到ui的運輸計畫。允許你將一條邊的時間降為0。同時開始所有的計畫,問最小要多少時間完成計畫。輸入輸出格式 輸入格式 輸入檔名為 transport.in。第一行包括兩個正整數 n m,表示 l 國中星球的數量及小 p 公司預接的運輸...
noip2015 運輸計畫
公元 2044 年,人類進入了宇宙紀元。l 國有 n 個星球,還有 n 1 條雙向航道,每條航道建立在兩個星球之間,這 n 1 條航道連通了 l 國的所有星球。小 p 掌管一家物流公司,該公司有很多個運輸計畫,每個運輸計畫形如 有一艘物流飛船需要從 ui 號星球沿最快的宇航路徑飛行到 vi 號星球去...
NOIP2015 運輸計畫
題目鏈結 codevs 4632 題目大意 在一棵 n 節點樹上,有 m個運輸計畫 從ai 到 bi n,m 300000 問 把哪一條樹邊的權值變為0,可以使所有運輸計畫的最大距離最小,輸出這個最大距離的最小值。分析 0.首先要會lca和樹上差分。1.顯然,這道題要求樹上兩點之間的距離,所以要寫l...