NOIP 2015 UOJ 150 運輸計畫

2021-07-23 22:00:18 字數 3218 閱讀 8718

公元 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 號星球去...