codevs 1036 商務旅行 (LCA)

2021-08-04 06:58:06 字數 1987 閱讀 3582

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

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

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

輸入檔案中的第一行有乙個整數n,1<=n<=30 000,為城鎮的數目。下面n-1行,每行由兩個整數a 和b (1<=a, b<=n; a<>b)組成,表示城鎮a和城鎮b有公路連線。在第n+1行為乙個整數m,下面的m行,每行有該商人需要順次經過的各城鎮編號。

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

5

1 21 5

3 54 541325

7
所有的道路都是雙向的,並且沒有環,因此我們可以根據邊來建樹。

如下圖(樣例):

依次經過1 33 22 5這幾條路徑,從圖中我們可以發現,路徑的長度剛好等於兩端點與其最近公共祖先的深度差之和。

於是:

1->3: de

p[1]

+dep

[3]−

2×de

p[1]

=1+3

−2=2

3->2: de

p[2]

+dep

[3]−

2×de

p[1]

=2+3

−2=3

2->5: de

p[2]

+dep

[5]−

2×de

p[1]

=2+2

−2=2

然後題目便轉化為基礎的 lca 問題咯~

#include

#include

#include

#include

using

namespace

std;

const

int maxn=31000;

int fa[maxn];

int rank[maxn];

bool visit[maxn];

vector

tree[maxn],qes[maxn];

int ancestor[maxn];

int ans;

int dep[maxn];

void init(int n)

}int find_set(int x) //並查集 查詢+路徑壓縮

void union_set(int x,int y) //並查集 合併

}void lca(int u,int pa,int deep)

visit[u]=true;

len = qes[u].size();

for(int i=0; iif(visit[qes[u][i]])

ans+=dep[u]+dep[qes[u][i]]-2*dep[ancestor[find_set(qes[u][i])]];

}}int data[maxn];

int main()

scanf("%d",&m);

for(int i=0; iscanf("%d",data+i);

if(i)

}lca(1,0,1);

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

}return

0;}

CodeVS1036 商務旅行

某首都城市的商人要經常到各城鎮去做生意,他們按自己的路線去做,目的是為了更好的節約時間。假設有n個城鎮,首都編號為1,商人從首都出發,其他各城鎮之間都有道路連線,任意兩個城鎮之間如果有直連道路,在他們之間行駛需要花費單位時間。該國公路網路發達,從首都出發能到達任意乙個城鎮,並且公路網路不會存在環。你...

Codevs 1036 商務旅行

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

Codevs 1036 商務旅行

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