NOIP2015 運輸計畫

2021-08-09 23:56:23 字數 1995 閱讀 6321

既然是noip的題目,那麼……

意料之中的偷懶不可避免

actually,剛開始看這道題目的時候沒有什麼想法,然後就手賤點開了標籤——樹鏈剖分!!!

於是我果斷就慫了,過了幾天,我現在又才繼續寫,發現好像也不一定需要樹鏈剖分,不過樹鏈剖分比較好寫吧可能。樹鏈剖分我只是看了看,也沒有實現了,好像就是將樹分成幾條鏈,這樣就可以在鏈上用線段樹快速維護出需要的資訊。當然,我還是先不談論這種高深的話題了。

如果等我學了樹鏈剖分之後,我還記得這件事的話,我就填坑。

首先,我們發現可以列舉這個最短距離k,而且還可以二分答案。我經過卡評測之後發現maxr設到2∗

1082 ∗10

8就可以a了。

其次為了好查詢距離,我們可以記錄每個節點到根節點的距離,再記錄每組運輸計畫兩節點的公共祖先,然後就可以利用su

m[x]

+sum

[y]−

2∗su

m[lc

a]s um

[x]+

sum[

y]−2

∗sum

[lca

]快速地算出距離。找出距離大於k的計畫,然後為了使它們的路徑距離變小,應該都需要建立蟲洞,那麼最優當然就是建立在它們的公共交點上,列舉這些交點即可判斷是否可行。

所以關鍵問題就在於如何快速求這個公共交點。對於乙個距離超過k的運輸計畫x->y,記錄路徑對節點的覆蓋次數,利用差分快速修改,ch

a[x]

+=1;

cha[

y]+=

1;ch

a[lc

a]−=

2 cha

[x]+

=1;c

ha[y

]+=1

;cha

[lca

]−=2

。最後在重新dfs一遍就可以獲得每個點的覆蓋次數。由於蟲洞只能改某條航道,那就記錄maxn為最長可能減少的距離,再與最長的路徑maxdis相比較,如果減去之後仍然大於列舉出的k,那麼顯然不成立,否則就可行。依次來二分答案。

貌似這道題還需要一點卡常技巧,我也不知道考noip的時候,能不能卡進去,但至少交到oj上a了。

#include 

#include

#include

#include

using

namespace

std;

const

int size=300010,maxr=200000000;

struct dataedge[size<<1];

int n,m,p,head[size],deep[size],pre[size][21];

int s[size],t[size],lca[size],cha[size],sum[size];

template

inline

void read(tp &x)

inline

int max(int x,int y)

inline

void insert(int u,int v,int w)

void dfs(int x,int fa)

}int getlca(int x,int y)

void input()

}void update(int x,int fa)

}bool check(int k)

update(1,0);

for(int i=2;i<=n;i++)

if(cha[i]>=num)

maxn=max(maxn,sum[i]-sum[pre[i][0]]);

if(maxdis-maxn>k)

return

false;

return

true;

}int main()

printf("%d\n",l);

return

0;}

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...

noip 2015 運輸計畫

去題面的傳送門 題目的意思是 求將一棵樹上的任意一條邊權賦值為0時,所有航線的最長長度的最小值 想到二分答案 如何驗證?既然我們二分的答案是最長路線,也就是說,在將一條邊權賦值為0之後,所有的路線長度應該都小於等於mid。但是只能刪掉一條邊,所以這條邊是所有刪邊之前長度小於mid的路線的交邊。問題轉...