poj1986 (LCA)

poj1986

给我们一棵树,求任意两个点之间的距离

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
",dist[a]-dist[LCA] + dist[b]-dist[LCA]);
108         }
109         
110         
111     }
112     
113     return 0;
114 }
原文地址:https://www.cnblogs.com/justPassBy/p/4515353.html