[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("\n"); 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\n",(t1+t2+t3)/2); 98 } 99 } 100 return 0; 101 }