How far away ?
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 28961 Accepted Submission(s): 11639
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
题目大意:给一个n个节点的带权树,m次询问,求两点之间的距离
第一行输入t,表示多个测试样例
第二行输入n,m,表示n个节点和m次询问
接下来n-1行,每行输入x,y,w,表示x到y的距离为w
最后m行每行输入两个数xx,yy,询问xx到yy的最短距离为多少
第一行输入t,表示多个测试样例
第二行输入n,m,表示n个节点和m次询问
接下来n-1行,每行输入x,y,w,表示x到y的距离为w
最后m行每行输入两个数xx,yy,询问xx到yy的最短距离为多少
这题给人的感觉就是最短路可以做,但是注意数据范围40000,开不了40000的二维数组,所以直接gg
但其实就是简单的最近公共祖先问题,找到x,y两点最近的公共祖先节点z[i],dis[x]+dis[y]-2*dis[z[i]]就是答案
#include<iostream> #include<string.h> #include<vector> using namespace std; struct node { int id; int len; }p; vector<node>mp[40005];//结构体动态数组 int dis[40005],xx[40005],yy[40005],vis[40005],z[40005],fa[40005];//dis是存距离,xx,yy存询问的点,z[i]表示i的LCA是点z[i],fa是存父亲节点 int t,n,m; void add(int a,int b,int c)//加边建树 { p.id=b; p.len=c; mp[a].push_back(p); } void init()//初始化 { for(int i=1;i<=n;i++) { fa[i]=i; mp[i].clear(); dis[i]=0; vis[i]=0; z[i]=0; } } int find(int x) { if(fa[x]!=x) return fa[x]=find(fa[x]); return fa[x]; } void join(int x,int y) { x=find(x); y=find(y); if(x!=y) fa[y]=x; } void tarjan(int x) { vis[x]=1; for(int i=0;i<mp[x].size();i++) { int y=mp[x][i].id; if(!vis[y])//未遍历过 { dis[y]=dis[x]+mp[x][i].len;//更新距离 tarjan(y);//遍历下一个点 join(x,y);//合并 } } for(int i=1;i<=m;i++) { if(xx[i]==x&&vis[yy[i]]) z[i]==find(yy[i]); if(yy[i]==x&&vis[xx[i]]) z[i]=find(xx[i]); } } int main() { cin>>t; while(t--) { cin>>n>>m; int a,b,c; init(); for(int i=1;i<n;i++)//描述边 { cin>>a>>b>>c; add(a,b,c); add(b,a,c); } for(int i=1;i<=m;i++)//询问 { cin>>xx[i]>>yy[i]; } tarjan(1); for(int i=1;i<=m;i++) cout<<dis[xx[i]]+dis[yy[i]]-2*dis[z[i]]<<endl; } return 0; }