HDU2586How far away ?
http://acm.hdu.edu.cn/showproblem.php?pid=2586
How far away ?
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 13821 Accepted Submission(s):
5195
Problem Description
There are n houses in the village and some
bidirectional roads connecting them. Every day peole always like to ask like
this "How far is it if I want to go from house A to house B"? Usually it hard to
answer. But luckily int this village the answer is always unique, since the
roads are built in the way that there is a unique simple path("simple" means you
can't visit a place twice) between every two houses. Yout task is to answer all
these curious people.
Input
First line is a single integer T(T<=10), indicating
the number of test cases.
For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
Output
For each test case,output m lines. Each line represents
the answer of the query. Output a bland line after each test case.
Sample Input
2
3 2
1 2 10
3 1 15
1 2
2 3
2 2
1 2 100
1 2
2 1
Sample Output
10
25
100
100
Source
题目大意:有T组数据 每组给出n个点由n-1条路连接,给出m次询问,求a和b两个村庄的距离
我实在不想吐槽,多组数据不用初始化也能A?中间把最近公共祖先输出了也能A!?逗我玩呢。
带领小学妹谢JustPenz233
#include <cstdio> #include <cstring> #include <iostream> #include <vector> using namespace std; vector<int> v[41000]; vector<int> w[41000]; int f[41000][21];//f[i][j]表示i点向上2^j层的祖先 int g[41000][21];//g[i][j]表示i点到从i向上2^j层的祖先的距离 int dep[41000]; int n,m; void dfs(int pos,int pre,int depth) { dep[pos]=depth; for(int i=0;i<v[pos].size();i++) { int t=v[pos][i]; if(t==pre) continue; f[t][0]=pos; g[t][0]=w[pos][i]; dfs(t,pos,depth+1); } } int query(int a,int b) { int sum=0; if(dep[a]<dep[b]) swap(a,b);//深度较深的点 for(int i=20;i>=0;i--)//找到a在深度dep[b]处的祖先 { if(dep[f[a][i]]>=dep[b]) { sum+=g[a][i];//a到该祖先的距离 a=f[a][i]; } } if(a==b) return sum;//挪到相同深度后如果在同一点直接return int x; for(int i=20;i>=0;i--)//否则a和b一起往上蹦跶 { if(f[a][i]!=f[b][i]) { sum+=g[a][i]; a=f[a][i]; sum+=g[b][i]; b=f[b][i]; } } return sum+g[a][0]+g[b][0];//最后蹦跶到最近公共祖先的下一层,所以要再加上上一层 } int main() { int T; cin>>T; while(T--) { scanf("%d%d",&n,&m); memset(dep,-1,sizeof dep);//多组数据我们初始化 memset(f,0,sizeof f); memset(g,0,sizeof g); for(int i=0;i<n;i++)//md v[i].clear(),w[i].clear(); for(int i=1;i<n;i++) { int x,y,c; cin>>x>>y>>c; v[x].push_back(y); w[x].push_back(c); v[y].push_back(x); w[y].push_back(c); } int xxx=v[1].size(); dfs(1,0,1);//dfs处理出每个点的深度,以及各种... for(int i=1;1<<i<=n;i++) for(int j=1;j<=n;j++) f[j][i]=f[f[j][i-1]][i-1], g[j][i]=g[f[j][i-1]][i-1]+g[j][i-1]; for(int i=1;i<=m;i++) { int x,y; cin>>x>>y; if(x==y) cout<<"0"<<endl; else cout<<query(x,y)<<endl; } } return 0; }