How far away?
Time limit:2000/1000 MS (java/others) Memory limit:32768/32768 K (java/others)
Total submission (s): 7739 Accepted Submission (s): 2769
Problem Descriptionthere is n houses in the village and some bidirectional roads connecting them. Every day peole "What is it if I am want to go from House A to house B"? Usually it hard to answer. But luckily int this village the answer was always unique, since the roads was built in the the-the-the-that-there is a unique simp Le path ("simple" means you can ' t visit a place twice) between every the houses. Yout task is to answer all these curious people.
Inputfirst line was a single integer T (t<=10), indicating the number of test cases.
For each test case,in the first line there is the numbers N (2<=n<=40000) and M (1<=m<=200), the number of hous Es and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning this there is a road con Necting House I and House j,with length K (0<k<=40000). The houses is labeled from 1 to N.
Next m lines each have distinct integers i and j, you areato answer the distance between House I and House J.
Outputfor each test case,output m lines. Each line represents the answer of the query. Output a bland line after all test case.
Sample Input
23 21 2 103 1 151 22 32 21 2 1001 22 1
Sample Output
1025100100
Approximate test instructions: Finding the distance between any two points in the tree is obviously the distance from the u,v to the root, minus the distance from their LCA to the root.
As a result of the study of LCA, three LCA methods have been used to find
Method one: Off-line algorithm Tarjan
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm>using namespace std;const int N = 40000+1000;int head[n];int fst[n];struct edge{int v,w,nxt,id;} Es[n<<1],qury[444];int cnt,qc;int ans[222];int fa[n],ance[n];void inline add_query (int u,int v,int ID) {QURY[QC]. V=v; Qury[qc].id=id; Qury[qc].nxt=fst[u]; fst[u]=qc++; Qury[qc].v=u; Qury[qc].id=id; QURY[QC].NXT=FST[V]; fst[v]=qc++;} void inline Add_edge (int u,int v,int W) {es[cnt].w=w; Es[cnt].v=v; Es[cnt].nxt=head[u]; head[u]=cnt++; Es[cnt].v=u; Es[cnt].w=w; ES[CNT].NXT=HEAD[V]; head[v]=cnt++;} int N,m;bool vis[n];int GETF (int x) {return x==fa[x]? X:FA[X]=GETF (Fa[x]);} void Merge (int u,int v) {fa[getf (U)]=getf (v);} void LCA (int u,int pa) {ance[u]=fa[u]=u; for (int i=head[u];~i;i=es[i].nxt) {int v=es[i].v; if (V==PA) continue; LCA (V,u); Merge (U,V); ANCE[GETF (v)]=u; } vis[u]=1; for (int i=fST[U];~I;I=QURY[I].NXT) {int v=qury[i].v; if (Vis[v]) ans[qury[i].id]=ance[getf (v)]; }}int dp[n];void MAKEDP (int u,int pa) {for (int i=head[u];~i;i=es[i].nxt) {int v=es[i].v,w=es[i].w; if (V==PA) continue; Dp[v]=dp[u]+w; MAKEDP (V,u); }}void Ini () {memset (head,-1,sizeof (head)); memset (fst,-1,sizeof (FST)); cnt=qc=0; memset (vis,0,sizeof (Vis));} int main () {int T; scanf ("%d", &t); while (t--) {ini (); scanf ("%d%d", &n,&m); for (int i=1;i<n;i++) {int u,v,w; scanf ("%d%d%d", &u,&v,&w); Add_edge (U,V,W); } for (int i=1;i<=m;i++) {int u,v; scanf ("%d%d", &u,&v); Add_query (U,v,i); } LCA (a); MAKEDP (a); for (int i=0;i<m;i++) {int j=i<<1; printf ("%d\n", Dp[qury[j].v]+dp[qury[j^1].v]-2*dp[ans[i+1]]); } } return 0;}
Method Two: BFs Multiplication hop Table algorithm
#include <cstdio> #include <iostream> #include <cstring> #include <queue> #include < algorithm>using namespace Std;const int N = 40000+1000;int head[n];struct edge{int v,w,nxt;} Es[n<<1];int cnt;inline void Add_edge (int u,int v,int W) {es[cnt].v=v; Es[cnt].w=w; Es[cnt].nxt=head[u]; head[u]=cnt++; Es[cnt].v=u; Es[cnt].w=w; ES[CNT].NXT=HEAD[V]; head[v]=cnt++;} int dp[n];int dep[n];bool vis[n];int pa[n][20];void bfs () {queue<int>q; Q.push (1); Pa[1][0]=1; Vis[1]=1; while (!q.empty ()) {int U=q.front (); Q.pop (); for (int i=1;i<20;i++) pa[u][i]=pa[pa[u][i-1]][i-1]; for (int i=head[u];~i;i=es[i].nxt) {int v=es[i].v,w=es[i].w; if (vis[v]==0) {vis[v]=1; Dp[v]=dp[u]+w; Pa[v][0]=u; dep[v]=dep[u]+1; Q.push (v); }}}}int LCA (int u,int v) {if (Dep[u]>dep[v]) Swap (U, v); for (int det=dep[v]-dep[u],i=0;det;i++,det>>=1) if (det&1) v=pa[v][i]; if (v==u) return v; for (int i=20-1;i>=0;i--) if (Pa[u][i]!=pa[v][i]) v=pa[v][i],u=pa[u][i]; return pa[u][0];} int n,m;void ini () {memset (head,-1,sizeof (head)); cnt=0; memset (vis,0,sizeof (VIS)); dp[1]=0;} int main () {int T; scanf ("%d", &t); while (t--) {scanf ("%d%d", &n,&m); INI (); for (int i=1;i<n;i++) {int u,v,w; scanf ("%d%d%d", &u,&v,&w); Add_edge (U,V,W); } BFS (); for (int i=1;i<=m;i++) {int u,v; scanf ("%d%d", &u,&v); int LCAV = LCA (u,v); int ans = DP[U]+DP[V]-2*DP[LCAV]; printf ("%d\n", ans); }} return 0;}
Method Three: DFS-based RMQ
#include <cstdio> #include <iostream> #include <cstring> #include <queue> #include < algorithm>using namespace Std;const int N = 40000+1000;int head[n];struct edge{int v,w,nxt;} Es[n<<1];int cnt;inline void Add_edge (int u,int v,int W) {es[cnt].v=v; Es[cnt].w=w; Es[cnt].nxt=head[u]; head[u]=cnt++; Es[cnt].v=u; Es[cnt].w=w; ES[CNT].NXT=HEAD[V]; head[v]=cnt++;} int dp[n];int index;int vs[n*3],id[n],dep[n];int lca[n*3][20];bool vis[n];void dfs (int u,int h) {vis[u]=1; Id[u]=++index; Vs[index]=u; Dep[u]=h; for (int i=head[u];~i;i=es[i].nxt) {int v=es[i].v,w=es[i].w; if (Vis[v]) continue; Dp[v]=dp[u]+w; DFS (V,H+1); Vs[++index]=u; }}int mm[n];void Ini () {memset (vis,0,sizeof (VIS)); memset (head,-1,sizeof (head)); cnt=index=0; dp[1]=0;} int N,m;int Main () {mm[0]=-1; for (int i=1;i<=n-1;i++) mm[i]= (((i-1) &i) ==0)? MM[I-1]+1:MM[I-1]; int T; scanf ("%d", &t); WhiLe (t--) {scanf ("%d%d", &n,&m); INI (); for (int i=1;i<n;i++) {int u,v,w; scanf ("%d%d%d", &u,&v,&w); Add_edge (U,V,W); } dfs (1,0); for (int i=1;i<=index;i++) lca[i][0]=vs[i]; for (int j=1;j<20;j++) for (int i=1;i+ (1<<J) -1<=index;i++) {int a=lca[i][j -1],b=lca[i+ (1<< (j-1))][j-1]; LCA[I][J] = dep[a]<dep[b]? A:B; } for (int i=1;i<=m;i++) {int u,v; scanf ("%d%d", &u,&v); int l=min (id[u],id[v]); int R=max (id[u],id[v]); int k=mm[r-l+1]; int a=lca[l][k],b=lca[r-(1<<k) +1][k]; int lcav = Dep[a]<dep[b]? A:B; int ans = DP[U]+DP[V]-2*DP[LCAV]; printf ("%d\n", ans); }} return 0;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
HDU 2586 how far away? (Beginner's LCA)