1. 程式人生 > >NOIP2015 運輸計劃

NOIP2015 運輸計劃

輸入格式 log ++ body bad span printf ora 物流

題目背景

公元 2044 年,人類進入了宇宙紀元。

題目描述

L 國有 n 個星球,還有 n-1 條雙向航道,每條航道建立在兩個星球之間,這 n-1 條航道連通了 L 國的所有星球。

小 P 掌管一家物流公司,該公司有很多個運輸計劃,每個運輸計劃形如:有一艘物

流飛船需要從 ui 號星球沿最快的宇航路徑飛行到 vi 號星球去。顯然,飛船駛過一條航道 是需要時間的,對於航道 j,任意飛船駛過它所花費的時間為 tj,並且任意兩艘飛船之 間不會產生任何幹擾。

為了鼓勵科技創新,L 國國王同意小 P 的物流公司參與 L 國的航道建設,即允許小 P 把某一條航道改造成蟲洞,飛船駛過蟲洞不消耗時間。

在蟲洞的建設完成前小 P 的物流公司就預接了 m 個運輸計劃。在蟲洞建設完成後, 這 m 個運輸計劃會同時開始,所有飛船一起出發。當這 m 個運輸計劃都完成時,小 P 的 物流公司的階段性工作就完成了。

如果小 P 可以自由選擇將哪一條航道改造成蟲洞,試求出小 P 的物流公司完成階段 性工作所需要的最短時間是多少?

輸入輸出格式

輸入格式:

輸入文件名為 transport.in。

第一行包括兩個正整數 n、m,表示 L 國中星球的數量及小 P 公司預接的運輸計劃的數量,星球從 1 到 n 編號。

接下來 n-1 行描述航道的建設情況,其中第 i 行包含三個整數 ai, bi 和 ti,表示第

i 條雙向航道修建在 ai 與 bi 兩個星球之間,任意飛船駛過它所花費的時間為 ti。

接下來 m 行描述運輸計劃的情況,其中第 j 行包含兩個正整數 uj 和 vj,表示第 j個 運輸計劃是從 uj 號星球飛往 vj 號星球。

輸出格式:

輸出 共1行,包含1個整數,表示小P的物流公司完成階段性工作所需要的最短時間。

輸入輸出樣例

輸入樣例#1: 復制
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

說明

所有測試數據的範圍和特點如下表所示

技術分享圖片

請註意常數因子帶來的程序效率上的影響。

氣死我了調了一晚上就是因為dif數組忘記清零

  1 //2018年2月14日19:17:34 
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5
using namespace std; 6 7 const int N = 3000001; 8 const int M = 3000001; 9 int n, m; 10 int x[N], y[N], LCA[N]; 11 int fir[N], edge_Num, nxt[M], to[M], w[M]; 12 int dis[N], ans; 13 void addEdge(int x, int y, int z){ 14 to[++edge_Num] = y; 15 w[edge_Num] = z; 16 nxt[edge_Num] = fir[x]; 17 18 fir[x] = edge_Num; 19 } 20 21 int p[N][23], deep[N], len[N]; 22 void dfs(int u){ 23 for(int i=1;i<=22;i++){ 24 if(deep[u] < (1<<i)) break; 25 p[u][i] = p[p[u][i-1]][i-1]; 26 } 27 for(int i=fir[u]; i; i=nxt[i]) 28 if(!deep[to[i]]){ 29 len[to[i]] = len[u] + w[i]; 30 deep[to[i]] = deep[u] + 1; 31 p[to[i]][0] = u; 32 dfs(to[i]); 33 } 34 } 35 36 int lca(int u, int v){ 37 if(deep[u] < deep[v]) swap(u, v); 38 int c = deep[u] - deep[v]; 39 for(int i=0;i<=22;i++) 40 if((1<<i) & c) 41 u = p[u][i]; 42 if(u == v) return u; 43 for(int i=22;i>=0;i--) 44 if(p[u][i] != p[v][i]){ 45 u = p[u][i]; 46 v = p[v][i]; 47 } 48 return p[u][0]; 49 } 50 int dif[N]; 51 void ddd(int x, int fa){ 52 for(int i=fir[x]; i; i=nxt[i]){ 53 if(to[i] != fa){ 54 ddd(to[i], x); 55 dif[x] += dif[to[i]]; 56 } 57 } 58 } 59 bool check(int mi){ 60 int num = 0; 61 int mx = 0; 62 memset(dif, 0, sizeof(dif)); //毒瘤啊, 一定不要忘記清零!!!!!! 63 for(int i=1;i<=m;i++){ 64 if(mi < dis[i]){ 65 num++; 66 dif[x[i]]++; 67 dif[y[i]]++; 68 dif[LCA[i]] -= 2; 69 mx = max(dis[i], mx); 70 } 71 } 72 ddd(1, 1); 73 for(int i=1; i<=n; i++){ 74 int fa = p[i][0]; 75 for(int j=fir[fa]; j; j=nxt[j]) 76 if(to[j] == i){ 77 if(num == dif[i] && mx-w[j] <= mi) 78 return true; 79 } 80 } 81 return false; 82 } 83 84 int l, r; 85 86 int main(){ 87 scanf("%d%d", &n, &m); 88 for(int i=1;i<n;i++){ 89 int x, y, z; 90 scanf("%d%d%d", &x, &y, &z); 91 addEdge(x, y, z); 92 addEdge(y, x, z); 93 } 94 p[1][0] = 1; 95 deep[1] = 1; 96 dfs(1); 97 for(int i=1;i<=m;i++){ 98 scanf("%d%d", &x[i], &y[i]); 99 LCA[i] = lca(x[i], y[i]); 100 dis[i] = len[x[i]] + len[y[i]] - 2*len[LCA[i]]; 101 r = max(r, dis[i]); 102 } 103 l = 1; 104 while(l <= r){ 105 int mid = (l + r) >> 1; 106 if(check(mid)) r = mid-1, ans = mid; 107 else l = mid+1; 108 } 109 printf("%d\n", ans); 110 111 return 0; 112 }

NOIP2015 運輸計劃