1. 程式人生 > >codevs 2370 小機房的樹

codevs 2370 小機房的樹

content anim ane forward 設計 codevs urn one 所在

http://codevs.cn/problem/2370/

2370 小機房的樹

時間限制: 1 s 空間限制: 256000 KB 題目等級 : 鉆石 Diamond 題目描述 Description

小機房有棵煥狗種的樹,樹上有N個節點,節點標號為0到N-1,有兩只蟲子名叫飄狗和大吉狗,分居在兩個不同的節點上。有一天,他們想爬到一個節點上去搞基,但是作為兩只蟲子,他們不想花費太多精力。已知從某個節點爬到其父親節點要花費 c 的能量(從父親節點爬到此節點也相同),他們想找出一條花費精力最短的路,以使得搞基的時候精力旺盛,他們找到你要你設計一個程序來找到這條路,要求你告訴他們最少需要花費多少精力

輸入描述 Input Description
第一行一個n,接下來n-1行每一行有三個整數u,v, c 。表示節點 u 爬到節點 v 需要花費 c 的精力。
第n+1行有一個整數m表示有m次詢問。接下來m行每一行有兩個整數 u ,v 表示兩只蟲子所在的節點
輸出描述 Output Description

一共有m行,每一行一個整數,表示對於該次詢問所得出的最短距離。

樣例輸入 Sample Input

3

1 0 1

2 0 1

3

1 0

2 0

1 2

樣例輸出 Sample Output

1

1

2

數據範圍及提示 Data Size & Hint

1<=n<=50000, 1<=m<=75000, 0<=c<=1000

#include<bits/stdc++.h>
using namespace std;
#define maxn 10000000

int n,head[maxn],m,s,x,y,z,num;
int size[maxn],deep[maxn],dad[maxn],top[maxn],dis[maxn];

struct Edge{
    int u,v,next,w;
}edge[maxn];

void ins(int u,int v,int w) { edge[++num].next=head[u]; edge[num].v=v; edge[num].w=w; head[u]=num; } void dfs(int x) { size[x]=1 ; deep[x]=deep[dad[x]]+1; for(int i=head[x];i;i=edge[i].next) { int v=edge[i].v; if(dad[x]==v) continue; dad[v]=x; dis[v]=dis[x]+edge[i].w; dfs(v); size[x]+=size[v]; } } void dfs2(int x) { int t=0; if(!top[x]) top[x]=x; for(int i=head[x];i;i=edge[i].next) { int v=edge[i].v; if(dad[x]!=v&&size[t]<size[v]) t=v; } if(t) top[t]=top[x],dfs2(t); for(int i=head[x];i;i=edge[i].next) { int v=edge[i].v; if(dad[x]!=v&&t!=v) dfs2(v); } } int lca(int x,int y) { for(;top[x]!=top[y];x=dad[top[x]]) if(deep[top[x]]<deep[top[y]]) swap(x,y); return deep[x]<deep[y]?x:y; } int main() { scanf("%d",&n); for(int i=1;i<n;i++) { scanf("%d%d%d",&x,&y,&z); ins(x,y,z); ins(y,x,z); } dfs(0); dfs2(0); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); int a=lca(x,y); printf("%d\n",dis[x]+dis[y]-2*dis[a]); } return 0; }

codevs 2370 小機房的樹