公元 2044 年,人類進入了宇宙紀元。第二次寫這個題,上次寫著寫著就吐了,這次又想起來這道題,寫了一下。l 國有 n 個星球,還有 n−1 條雙向航道,每條航道建立在兩個星球之間,這 n−1條航道連通了 l 國的所有星球。 小 p掌管一家物流公司, 該公司有很多個運輸計畫,每個運輸計畫形如:有一艘物流飛船需要從 ui號星球沿最快的宇航路徑飛行到 vi號星球去。顯然,飛船駛過一條航道是需要時間的,對於航道 j,任意飛船駛過它所花費的時間為 tj,並且任意兩艘飛船之間不會產生任何干擾。
為了鼓勵科技創新, l 國國王同意小 p 的物流公司參與 l 國的航道建設,即允許小p把某一條航道改造成蟲洞,飛船駛過蟲洞不消耗時間。
在蟲洞的建設完成前小 p 的物流公司就預接了 m 個運輸計畫。在蟲洞建設完成後,這 m個運輸計畫會同時開始,所有飛船一起出發。當這 m個運輸計畫都完成時,小 p 的物流公司的階段性工作就完成了。 如果小 p可以自由選擇將哪一條航道改造成蟲洞, 試求出小 p的物流公司完成階段性工作所需要的最短時間是多少?
輸入格式
第一行包括兩個正整數 n,m,表示 l 國中星球的數量及小 p 公司預接的運輸計畫的數量,星球從 11 到 n 編號。
接下來n−1 行描述航道的建設情況,其中第 i 行包含三個整數 ai,,bi 和 ti,表示第 i 條雙向航道修建在ai 與 bi兩個星球之間,任意飛船駛過它所花費的時間為ti。資料保證 1≤ai,bi≤n 且0≤ti≤1000。
接下來 m 行描述運輸計畫的情況,其中第 j 行包含兩個正整數 uj 和 vj,表示第 j 個運輸計畫是從 uj號星球飛往vj號星球。資料保證 1≤ui,vi≤n
輸出格式
輸出檔案只包含乙個整數,表示小 p 的物流公司完成階段性工作所需要的最短時間。
樣例一
input
6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5output
explanation
將第 1 條航道改造成蟲洞: 則三個計畫耗時分別為:11,12,11,故需要花費的時間為 12。
將第 2 條航道改造成蟲洞: 則三個計畫耗時分別為:7,15,11,故需要花費的時間為 15。
將第 3 條航道改造成蟲洞: 則三個計畫耗時分別為:4,8,11,故需要花費的時間為 11。
將第 4 條航道改造成蟲洞: 則三個計畫耗時分別為:11,15,5,故需要花費的時間為 15。
將第 5 條航道改造成蟲洞: 則三個計畫耗時分別為:11,10,6,故需要花費的時間為 11。
故將第 3 條或第 5 條航道改造成蟲洞均可使得完成階段性工作的耗時最短,需要花費的時間為 11。
限制與約定
吐槽一下:寫完之後去codevs交,怎麼優化最後乙個點都是tle,本機跑……也得要1.5s,然後想到uoj【滑稽。去uoj上去交,woc最後乙個點900ms過了……uoj真是太強啦!
首先看到這個題是最大時間最短,可以想到二分。而在樹上的話,顯然要求lca。
那麼每次二分完乙個答案要怎麼驗證呢?列舉哪個計畫的耗時超過了答案,那麼我們就要在這條路徑上設定蟲洞,那具體在哪條邊上設定蟲洞呢?如果有k個計畫的耗時超過了答案ans,那我們找一條被覆蓋了k次的邊進行修改肯定是最優的,這就用到了樹上字首和。
如果乙個計畫的耗時超過了ans,我們在u,v處+1,在lca(u,v)處-2。最後更新樹上的字首和,找到那條邊。如果最大耗時減去那條邊的花費小於ans,返回true:否則返回false。
記得每次檢驗答案的時候,要清空陣列!!!
#include
#include
#include
#include
using
namespace
std;
const
int sz = 300010;
const
int inf = 1e9;
struct edge
es[sz << 1];
struct plan
p[sz];
int first[sz << 1], nxt[sz << 1], tot = 1;
int n, m, depth[sz], fa[sz], dis[sz], jump[sz][25];
int recover[sz], in[sz], cnt, cost[sz];
bool vis[sz];
void read(int &num)
while('0'
<= c && c <= '9')
num *= f;
}void build(int f, int t, int d)
; nxt[tot] = first[f];
first[f] = tot;
}void dfs(int u)
}int get_lca(int u, int v)
if(u == v) return v;
return jump[u][0];
}bool check(int mid)
for(int i = cnt; i >= 1; i--)
recover[jump[in[i]][0]] += recover[in[i]];
for(int i = 1; i <= n; i++)
if(recover[i] == tot)
if(maxx - cost[i] <= mid) return
true;
return
false;
}int main()
dfs(1);
for(int i = 1; i <= m; i++)
int l = 0, r = inf, mid, ans = -1;
while(l <= r)
printf("%d", l);
fclose(stdin);
fclose(stdout);
return
0;}
uoj150 NOIP2015 運輸計畫
題目鏈結 給出一棵樹以及m個詢問,可以將樹上一條邊的權值修改為0,求經過這樣的修改之後最長的邊最短是多少。老早就聽說過這道題了,好像使用樹鏈剖分。先樹鏈剖分求出每個詢問的路程,最長的最短,可以用二分做。二分最長的邊的大小,也就是最後的答案,問題來了,怎麼判斷這個答案是否可行呢?我們記錄下所有超出當前...
Luogu2680 NOIp2015 運輸計畫
傳送門 sol 最暴力的做法就是列舉最長鏈上的邊,然後再算一次所有的鏈長,更新 ans 這裡要求最大的最小,容易想到二分答案.對於二分的值 mid 掃一遍所有的鏈,若鏈長小於等於 mid 那麼是合法的不需要處理的.否則,就記錄鏈上所有的邊經過的次數 1 最後找到被經過次數等於鏈長大於 mid 的鏈數...
noip2015 運輸計畫
公元 2044 年,人類進入了宇宙紀元。l 國有 n 個星球,還有 n 1 條雙向航道,每條航道建立在兩個星球之間,這 n 1 條航道連通了 l 國的所有星球。小 p 掌管一家物流公司,該公司有很多個運輸計畫,每個運輸計畫形如 有一艘物流飛船需要從 ui 號星球沿最快的宇航路徑飛行到 vi 號星球去...