hdu 2586 How far away
How far away ?
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 11699 Accepted Submission(s): 4300
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
ECJTU 2009 Spring Contest
一道lca入门题,题目大意是给定n户房屋,n-1条道路,询问两两房屋间的距离。我的思路是,由于是无向图,所以无固定树根,任意选节点都可。所以,先选定点1作为根,进行bfs和树上倍增。最终用距离公式dis[x]+dis[y]-2*dis[lca(x,y)]求出两房屋间的距离,其实这个公式还是蛮易懂的。不过在next这个数组名上栽了,CE滚粗。只好忍痛将next改为mnext,降低可读性。。。
17486822 2016-07-10 21:36:39 Accepted 2586 31MS 10308K 2038B G++ ksq2013
hdu上测的,不知道为什么用宽搜比我的同学慢了两倍,是因为数组开太大吗???真心无语。。。
一道lca入门题,题目大意是给定n户房屋,n-1条道路,询问两两房屋间的距离。我的思路是,由于是无向图,所以无固定树根,任意选节点都可。所以,先选定点1作为根,进行bfs和树上倍增。最终用距离公式dis[x]+dis[y]-2*dis[lca(x,y)]求出两房屋间的距离,其实这个公式还是蛮易懂的。不过在next这个数组名上栽了,CE滚粗。只好忍痛将next改为mnext,降低可读性。。。
17486822 2016-07-10 21:36:39 Accepted 2586 31MS 10308K 2038B G++ ksq2013
hdu上测的,不知道为什么用宽搜比我的同学慢了两倍,是因为数组开太大吗???真心无语。。。
#include<cstdio> #include<cstring> #include<iostream> using namespace std; bool vis[80100]; int n,bin[20],q[50100],dis[80100],deep[80100],fa[80100][20]; int u[80100],v[80100],w[80100],first[80100],mnext[80100]; void make_bin() { bin[0]=1; for(int i=1;i<=16;i++) bin[i]=bin[i-1]<<1; } void Init() { memset(vis,false,sizeof(vis)); memset(fa,0,sizeof(fa)); memset(mnext,0,sizeof(mnext)); memset(first,0,sizeof(first)); memset(q,0,sizeof(q)); memset(dis,0,sizeof(dis)); memset(deep,0,sizeof(deep)); } void Link() { for(int i=1;i<=n-1;i++){ scanf("%d%d%d",&u[i],&v[i],&w[i]); u[i+n-1]=v[i];v[i+n-1]=u[i];w[i+n-1]=w[i]; mnext[i]=first[u[i]]; mnext[i+n-1]=first[v[i]]; first[i]=i; first[v[i]]=i+n-1; } } void bfs() { int head=0,tail=1; q[0]=1;vis[1]=true; while(head^tail){ int now=q[head];head++; for(int i=1;i<=16;i++) if(bin[i]<=deep[now]) fa[now][i]=fa[fa[now][i-1]][i-1]; else break; for(int i=first[now];i&&v[i]^now;i=mnext[i]) if(!vis[v[i]]){ vis[v[i]]=true; fa[v[i]][0]=now; deep[v[i]]=deep[now]+1; dis[v[i]]=dis[now]+w[i]; q[tail++]=v[i]; } } } int lca(int x,int y) { int t=deep[x]-deep[y]; for(int i=0;i<=16;i++) if(t&bin[i]) x=fa[x][i]; for(int i=16;i>=0;i--) if(fa[x][i]^fa[y][i]) x=fa[x][i],y=fa[y][i]; if(!(x^y))return y; return fa[x][0]; } int main() { make_bin(); int T; scanf("%d",&T); for(;T;T--){ Init(); int m; scanf("%d%d",&n,&m); Link(); bfs(); for(int x,y;m;m--){ scanf("%d%d",&x,&y); if(deep[x]<deep[y])swap(x,y); printf("%d\n",dis[x]+dis[y]-2*dis[lca(x,y)]); } } return 0; }