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

2370 小機房的樹

anim -s app problem out code clas desc oid

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

 1 #include<iostream>
 2 #include<vector>
 3 using namespace std;
 4 typedef unsigned long long ll;
 5 const int maxn=50005,maxm=75005;
 6 
 7 
 8 vector<int> G[maxn],dist[maxn],u[maxn],f[maxn];
9 bool vis[maxn],vt[maxn]; 10 int fa[maxn],w[maxm],n; 11 ll anc[maxn]; 12 13 int find(int x) 14 { 15 if(!fa[x])return x; 16 return fa[x]=find(fa[x]); 17 } 18 19 void uni(int x,int y) 20 { 21 int b=find(y); 22 if(b!=x)fa[b]=x; 23 } 24 25 void Tarjan(int x,ll k) 26 { 27 anc[x]=k; 28 for(int i=0;i<G[x].size();i++) 29 if(!vt[G[x][i]]) 30 { 31 int v=G[x][i]; 32 vt[v]=true; 33 Tarjan(v,k+dist[x][i]); 34 uni(x,v); 35 } 36 vis[x]=true; 37 for(int i=0;i<u[x].size();i++) 38 if(vis[u[x][i]]) 39 { 40 w[f[x][i]]=anc[x]+anc[u[x][i]]-2*anc[find(u[x][i])]; 41 } 42 } 43 int main() 44 { 45 int a,b,c,m; 46 cin>>n; 47 for(int i=1;i<=n-1;i++) 48 { 49 cin>>a>>b>>c; 50 a++,b++; 51 G[a].push_back(b),dist[a].push_back(c); 52 G[b].push_back(a),dist[b].push_back(c); 53 } 54 cin>>m; 55 for(int i=1;i<=m;i++) 56 { 57 cin>>a>>b; 58 a++,b++; 59 u[a].push_back(b),u[b].push_back(a); 60 f[a].push_back(i),f[b].push_back(i); 61 } 62 vt[1]=true; 63 Tarjan(1,0); 64 //for(int i=1;i<=n;i++)cout<<anc[i]<<endl; 65 for(int i=1;i<=m;i++) 66 cout<<w[i]<<endl; 67 }

2370 小機房的樹