poj1986 (LCA)
给我们一棵树,求任意两个点之间的距离
dist[a->b] = dist[a] +dist[b] - 2*lca(a,b)
要建双向边,数据可能不是严格意义上的树
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <algorithm> 5 #include <iostream> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <string> 12 #include <math.h> 13 using namespace std; 14 #pragma warning(disable:4996) 15 typedef long long LL; 16 const int INF = 1<<30; 17 /* 18 19 */ 20 struct Edge 21 { 22 int to,dist; 23 }; 24 const int MAX_LOG_V = 100; 25 const int MAX_V = 100000+10; 26 int parent[MAX_LOG_V][MAX_V]; 27 int depth[MAX_V]; 28 int dist[MAX_V]; 29 vector<Edge> g[MAX_V]; 30 void dfs(int u, int fa, int d) 31 { 32 parent[0][u] = fa; 33 depth[u] = d; 34 for(int i=0; i<g[u].size(); ++i) 35 if(g[u][i].to!=fa) 36 { 37 dist[g[u][i].to] = dist[u] + g[u][i].dist; 38 dfs(g[u][i].to,u,d+1); 39 } 40 } 41 void init(int root, int n) 42 { 43 dfs(root,-1,0); 44 //预处理出parent 45 for(int k=0; k+1<MAX_LOG_V; ++k) 46 { 47 for(int v=1; v<=n; ++v) 48 { 49 if(parent[k][v]<0) 50 parent[k+1][v] = -1; 51 else 52 parent[k+1][v] = parent[k][parent[k][v]]; 53 } 54 } 55 } 56 int lca(int u, int v) 57 { 58 if(depth[u] < depth[v]) 59 swap(u,v); 60 //让u和v走到同一生度 61 for(int k=0; k<MAX_LOG_V; ++k) 62 if((depth[u]-depth[v])>>k&1)//一个数能分解成多个二进制数相加,所以如果&1 为true,那么就向上走 63 u = parent[k][u]; 64 if(u==v) return u; 65 //达到同一深度后,二分搜索lca 66 67 for(int k=MAX_LOG_V-1; k>=0; --k) 68 if(parent[k][v]!=parent[k][u]) 69 {//我们并不知道要向上走多少步,但是只要每次走后, 70 //parent[k][v]!=parent[k][u],那么这一步就可以向上走,即将要走的步数分解为 1 + 2 + 4 + 8 + ...最后一步将在循环结束后走出 71 u = parent[k][u]; 72 v = parent[k][v]; 73 } 74 return parent[0][u]; 75 } 76 77 int main() 78 { 79 int n,a,m,i,b,t,root,c; 80 char str[2]; 81 Edge tmp; 82 while(scanf("%d%d",&n,&m)!=EOF) 83 { 84 85 for(i=1; i<=n; ++i) 86 { 87 parent[0][i] = -1; 88 g[i].clear(); 89 } 90 for(i=0; i<n-1; ++i) 91 { 92 scanf("%d%d%d%s",&a,&b,&c,str); 93 tmp.to = b; 94 tmp.dist = c; 95 g[a].push_back(tmp); 96 tmp.to = a; 97 g[b].push_back(tmp); 98 } 99 root = 1; 100 dist[root] = 0; 101 init(root,n); 102 scanf("%d",&m); 103 for(i=0; i<m; ++i) 104 { 105 scanf("%d%d",&a,&b); 106 int LCA = lca(a,b); 107 printf("%d\n",dist[a]-dist[LCA] + dist[b]-dist[LCA]); 108 } 109 110 111 } 112 113 return 0; 114 }