[zoj3195]Design the city(LCA)

解题关键:求树上三点间的最短距离。

解题关键:$ans = (dis(a,b) + dis(a,c) + dis(b,c))/2$

  1 //#pragma comment(linker, "/STACK:1024000000,1024000000")
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cstdlib>
  6 #include<cmath>
  7 #include<iostream>
  8 typedef long long ll;
  9 using namespace std;  
 10 const int maxn=51000; 
 11 const int maxm=30;  
 12 int _pow[maxm],m,n;  
 13 int head[maxn],tot;
 14 int ver[maxn*2],depth[maxn*2],first[maxn],rmq[maxn*2][25],id;//5个数组,注意哪个需要乘2 
 15 int dis[maxn];
 16 inline int read(){
 17     char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar());
 18     int x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=(x<<3)+(x<<1)+ls-'0';
 19     if(k=='-')x=0-x;return x;
 20 }
 21 
 22 struct edge{
 23     int to,w,nxt;  
 24 }e[maxn*2];//链式前向星建树 
 25 
 26 void init(){
 27     memset(head,-1,sizeof head);
 28     tot=0;
 29     id=0;
 30 }
 31 
 32 void add_edge(int u,int v,int w){  
 33     e[tot].to=v;
 34     e[tot].w=w;
 35     e[tot].nxt=head[u];
 36     head[u]=tot++;
 37 }
 38   
 39 void dfs(int u,int fa,int dep){
 40     ver[++id]=u;//第i个访问到的结点编号 
 41     depth[id]=dep;//第i个访问到的结点深度  
 42     first[u]=id;
 43     for(int i=head[u];i!=-1;i=e[i].nxt){
 44         int v=e[i].to;
 45         int w=e[i].w;
 46         if(v==fa) continue;
 47         dis[v]=dis[u]+w;//dis是先序遍历求 
 48         dfs(v,u,dep+1);
 49         ver[++id]=u;//后序遍历,再次访问父节点 
 50         depth[id]=dep;
 51     }
 52 }
 53 
 54 void rmq_init(int n){
 55     int k=int(log(n)/log(2));
 56     for(int i=1;i<=n;++i)    rmq[i][0]=i;  
 57     for(int j=1;j<=k;++j){  
 58         for(int i=1;i+_pow[j]-1<=n;++i){//因为存的是索引 
 59             int a=rmq[i][j-1],b=rmq[i+_pow[j-1]][j-1];  
 60             rmq[i][j]=depth[a]<depth[b]?a:b;
 61         }
 62     }
 63 }
 64   
 65 int rmq_query(int l,int r){
 66     int k=int(log(r-l+1.0)/log(2.0));  
 67     int a=rmq[l][k],b=rmq[r-_pow[k]+1][k];  
 68     return depth[a]<depth[b]?a:b;
 69 }//返回的依然是索引 
 70   
 71 int LCA(int u,int v){
 72     int x=first[u],y=first[v];  
 73     if(x>y)swap(x,y);  
 74     int res=rmq_query(x,y);  
 75     return ver[res]; 
 76 }
 77 
 78 int main(){
 79     for(int i=0;i<maxm;++i)    _pow[i]=1<<i; //预处理2^n 
 80     int t,a,b,c,d,x=0;
 81     while(scanf("%d",&n)!=EOF){
 82         if(x++) printf("
");
 83         init();
 84         for(int i=0;i<n-1;++i){
 85             a=read()+1,b=read()+1,c=read();
 86             add_edge(a,b,c);
 87             add_edge(b,a,c);
 88         }
 89         dfs(1,-1,0);
 90         rmq_init(2*n-1);
 91         d=read();
 92         for(int i=0;i<d;++i){
 93             a=read()+1;b=read()+1;c=read()+1;
 94             int t1=LCA(a,b);t1=dis[a]+dis[b]-2*dis[t1];
 95             int t2=LCA(b,c);t2=dis[b]+dis[c]-2*dis[t2];
 96             int t3=LCA(a,c);t3=dis[a]+dis[c]-2*dis[t3];
 97             printf("%lld
",(t1+t2+t3)/2);
 98         }
 99     }
100     return 0;
101 }
原文地址:https://www.cnblogs.com/elpsycongroo/p/7470623.html