公元 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 公司預接的運輸計畫的數量,星球從 1 到 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 的物流公司完成階段性工作所需要的最短時間。
6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5樣例解釋:
將第 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。
95%: n, m <= 100000
100%:n, m <= 300000
有40%的資料成一條鏈
預處理每個計畫的lca以及路徑長。然後二分答案,然後判斷可行性,判斷時並不會什麼樹剖之類的高階演算法,所以用了gty講課時提到的樹上字首和。設有x個計畫比二分的答案要長,對於每乙個這樣的計畫,起點與終點打上+1的字首和標記,lca上打上-2的字首和標記。然後dfs一遍合併標記,找出所有標記數量等於x的點(對應其上面的那條邊)中邊權最大的,將最長計畫減去它的長度。若小於二分的答案,則代表此二分的答案可行,否則不行。
因為卡常lca並且我太弱了不會tarjan,所以下面的**是95分的。
另外,用對陣列的差分可以在10分鐘內拿到在鏈上的40分。
#include
#include
#include
#include
#define maxn 600500
using
namespace
std;
struct edgee[maxn];
struct planc[maxn];
long
long n, m, k, ww;
int d[maxn], book[maxn], p[maxn];
int st[maxn][30], a[maxn], fi[maxn];
long
long st_len[maxn][30];
bool cmp(plan a, plan b)
void add_edge(int u, int v, int w, int i)
void build_tree(int x, int fa, int dep)
}}void lca_maker()
}int lca(int x, int y, int i)
for(int j = 21; j >= 0; j--)
if(st[x][j] != st[y][j])
if(x != y)
c[i].len = ans;
return x;
}int dfs(int x, int fa)
now += book[x];
if(now == k && ww < st_len[x][0])
return now;
}int main()
build_tree(1, -1, 1);
lca_maker();
for(int i = 1; i <= m; i++)
c[i].lca = lca(c[i].x, c[i].y, i);
}sort(c+1, c+1+m, cmp);
long
long l = 1, r = 2147483647;
while(1)
for(int i = 1; i <= m; i++)
}if(k != 0) dfs(1, -1);
if(c[1].len - ww <= m) //當前解可行
r = m;
else
l = m+1;
}}
NOIP2015 運輸計畫
題目鏈結 codevs 4632 題目大意 在一棵 n 節點樹上,有 m個運輸計畫 從ai 到 bi n,m 300000 問 把哪一條樹邊的權值變為0,可以使所有運輸計畫的最大距離最小,輸出這個最大距離的最小值。分析 0.首先要會lca和樹上差分。1.顯然,這道題要求樹上兩點之間的距離,所以要寫l...
noip 2015 運輸計畫
去題面的傳送門 題目的意思是 求將一棵樹上的任意一條邊權賦值為0時,所有航線的最長長度的最小值 想到二分答案 如何驗證?既然我們二分的答案是最長路線,也就是說,在將一條邊權賦值為0之後,所有的路線長度應該都小於等於mid。但是只能刪掉一條邊,所以這條邊是所有刪邊之前長度小於mid的路線的交邊。問題轉...
NOIP2015 運輸計畫
既然是noip的題目,那麼 意料之中的偷懶不可避免 actually,剛開始看這道題目的時候沒有什麼想法,然後就手賤點開了標籤 樹鏈剖分!於是我果斷就慫了,過了幾天,我現在又才繼續寫,發現好像也不一定需要樹鏈剖分,不過樹鏈剖分比較好寫吧可能。樹鏈剖分我只是看了看,也沒有實現了,好像就是將樹分成幾條鏈...