CodeVS1036 商務旅行

2021-07-04 06:59:27 字數 3300 閱讀 5270

某首都城市的商人要經常到各城鎮去做生意,他們按自己的路線去做,目的是為了更好的節約時間。

假設有n個城鎮,首都編號為1,商人從首都出發,其他各城鎮之間都有道路連線,任意兩個城鎮之間如果有直連道路,在他們之間行駛需要花費單位時間。該國公路網路發達,從首都出發能到達任意乙個城鎮,並且公路網路不會存在環。

你的任務是幫助該商人計算一下他的最短旅行時間。

輸入檔案中的第一行有乙個整數

n ,

1<=

n<=

30000

,為城鎮的數目。下面n−

1 行,每行由兩個整數

a 和b(

1≤a,

b≤n;

a≠b)

組成,表示城鎮

a 和城鎮

b有公路連線。在第n+

1 行為乙個整數

m ,下面的

m行,每行有該商人需要順次經過的各城鎮編號。

在輸出檔案中輸出該商人旅行的最短時間。

5

1 21 5

3 54 541

325

7
題意很清楚,求起點至終點每兩個點的最短路徑之和,而這個圖退化成了一棵樹,我們可以想到求出兩點的lc

a 再進行根據深度計算。具體來說,在以t為根的樹中,對於兩點

u ,v,

lca(

t,u,

v)=p

,則di

st(u

,v)=

dep(

u)+d

ep(v

)−2∗

dep(

p)。

參考**如下:

type struct = record

go,next:longint;

end;

var n,m,ans,cnt,cntr:longint;

a:array[0..60200] of struct; //儲存邊

en,enr,father,depth:array[0..30100] of longint;

visited:array[0..30100] of boolean; //儲存訪問記錄

road:array[0..30100] of struct; //儲存詢問

procedure

addedge

(u,v:longint);

//增加一條邊

begin

inc(cnt); a[cnt].go:=v; a[cnt].next:=en[u]; en[u]:=cnt;

end;

procedure

addroad

(u,v:longint);

//增加乙個詢問

begin

inc(cntr); road[cntr].go:=v; road[cntr].next:=enr[u]; enr[u]:=cntr;

end;

procedure

init;

//讀入邊

var i,x,y:longint;

begin

readln(n);

fillchar(a,sizeof(a),0);

for i:=1

to n-1

dobegin

readln(x,y); addedge(x,y); addedge(y,x);

end;

end;

function

getfather

(x:longint):longint;

begin

if father[x]<>x then father[x]:=getfather(father[x]);

exit(father[x]);

end;

procedure

tarjan

(x,fa:longint);

//樸素tarjan演算法

var i,tmp,t1,t2,t3:longint;

begin

father[x]:=x;

i:=en[x];

while (i<>0) do

begin

tmp:=a[i].go;

i:=a[i].next;

if tmp=fa then

continue;

tarjan(tmp,x);

father[tmp]:=x;

end;

visited[x]:=true;

i:=enr[x];

while (i<>0) do

begin

tmp:=road[i].go;

i:=road[i].next;

if visited[tmp] then

begin

t1:=getfather(tmp);

inc(ans,depth[x]+depth[tmp]-2*depth[t1]);

end;

end;

end;

procedure

calcdep

(x,fa:longint);

//計算每個點深度(單獨計算可提高速度)

var i,tmp:longint;

begin

i:=en[x];

while (i<>0) do

begin

tmp:=a[i].go;

i:=a[i].next;

if tmp=fa then

continue;

depth[tmp]:=depth[x]+1;

calcdep(tmp,x);

end;

end;

procedure

main;

//讀取詢問並計算

var i,t,k:longint;

begin

readln(m); readln(t);

for i:=2

to m do

begin

readln(k);

addroad(t,k); addroad(k,t);

t:=k;

end;

fillchar(visited,sizeof(visited),false);

depth[1]:=1;

calcdep(1,1);

tarjan(1,1);

writeln(ans);

end;

begin

init;

main;

end.

Codevs 1036 商務旅行

1036 商務旅行 時間限制 1 s 空間限制 128000 kb 題目等級 鑽石 diamond 傳送門題目描述 description 某首都城市的商人要經常到各城鎮去做生意,他們按自己的路線去做,目的是為了更好的節約時間。假設有n個城鎮,首都編號為1,商人從首都出發,其他各城鎮之間都有道路連線...

Codevs 1036 商務旅行

時間限制 1 s 空間限制 128000 kb 題目等級 鑽石 diamond 題目描述 假設有n個城鎮,首都編號為1,商人從首都出發,其他各城鎮之間都有道路連線,任意兩個城鎮之間如果有直連道路,在他們之間行駛需要花費單位時間。該國公路網路發達,從首都出發能到達任意乙個城鎮,並且公路網路不會存在環。...

Codevs 1036 商務旅行

時間限制 1 s 空間限制 128000 kb 題目等級 鑽石 diamond 題目描述 假設有n個城鎮,首都編號為1,商人從首都出發,其他各城鎮之間都有道路連線,任意兩個城鎮之間如果有直連道路,在他們之間行駛需要花費單位時間。該國公路網路發達,從首都出發能到達任意乙個城鎮,並且公路網路不會存在環。...