hdu 2586(Tarjan 离线算法)
How far away ?
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 14809 Accepted Submission(s): 5621
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
LCA离线做法的板子 Tarjan算法(DFS+并查集)
不想解释 我就想贴个板子
#include<iostream> #include<cstdio> #include<cmath> #include<map> #include<cstdlib> #include<vector> #include<set> #include<queue> #include<cstring> #include<string.h> #include<algorithm> typedef long long ll; typedef unsigned long long LL; using namespace std; const int N=40000+100; int head[N]; int vis[N]; int parent[N]; int ans[N]; int cnt; vector<int>q[N]; vector<int>Q[N]; int dis[N]; int n; int ancestor[N]; struct node{ int to,next,w; }edge[2*N+10]; void init(){ cnt=0; memset(ans,0,sizeof(ans)); memset(dis,0,sizeof(dis)); memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); for(int i=0;i<=n;i++){ parent[i]=i; Q[i].clear(); q[i].clear(); } } void add(int u,int v,int w){ edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } int find(int x){ int r=x; while(r!=parent[x])r=parent[r]; int i=x; int j; while(parent[i]!=r){ j=parent[i]; parent[i]=r; i=j; } return r; } void Union(int x,int y){ x=find(x); y=find(y); if(x!=y)parent[y]=x; } void Tarjan(int x,int w){ vis[x]=1; dis[x]=w; //cout<<dis[x]<<endl; for(int i=head[x];i!=-1;i=edge[i].next){ int v=edge[i].to; if(vis[v])continue; Tarjan(v,w+edge[i].w); Union(x,v); ancestor[find(x)]=x; } for(int i=0;i<q[x].size();i++){ int u=q[x][i]; if(vis[u]){ int t=ancestor[find(u)]; ans[Q[x][i]]=dis[x]+dis[u]-dis[t]*2; } } } int main(){ int m; int t; scanf("%d",&t); while(t--){ init(); scanf("%d%d",&n,&m); int u,v,w; for(int i=0;i<n-1;i++){ scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } for(int i=0;i<m;i++){ scanf("%d%d",&u,&v); q[u].push_back(v); q[v].push_back(u); Q[u].push_back(i); Q[v].push_back(i); } Tarjan(1,0); // for(int i=1;i<=n;i++)cout<<dis[i]<<" "; //cout<<endl; for(int i=0;i<m;i++){ // cout<<4<<endl; cout<<ans[i]<<endl; } } }