码迷,mamicode.com
首页 > 其他好文 > 详细

[poj1986]Distance Queries(LCA)

时间:2017-09-03 15:35:48      阅读:88      评论:0      收藏:0      [点我收藏+]

标签:str   span   swap   for   ack   scanf   code   first   namespace   

解题关键:LCA模板题

复杂度:$O(n\log n)$

  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=81000; 
 11 const int maxm=25;  
 12 int _pow[maxm],m,n;  
 13 int head[maxn],tot;  
 14 int ver[maxn*2],depth[maxn*2],first[maxn],rmq[maxn*2][maxm],id;//5个数组,注意哪个需要乘2 
 15 ll 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             if(depth[a]<depth[b])    rmq[i][j]=a;  
 61             else  rmq[i][j]=b;  
 62         }
 63     }
 64 }
 65   
 66 int rmq_query(int l,int r){
 67     int k=int(log(r-l+1.0)/log(2.0));  
 68     int a=rmq[l][k],b=rmq[r-_pow[k]+1][k];  
 69     if(depth[a]<depth[b])  return a;  
 70     else  return b;
 71 }//返回的依然是索引 
 72   
 73 int LCA(int u,int v){
 74     int x=first[u],y=first[v];  
 75     if(x>y)swap(x,y);  
 76     int res=rmq_query(x,y);  
 77     return ver[res]; 
 78 }
 79 
 80 int main(){
 81     for(int i=0;i<maxn;++i)    _pow[i]=1<<i; //预处理2^n 
 82     int t,a,b,c;
 83     init();
 84     n=read(),m=read();
 85     for(int i=0;i<m;++i){
 86         scanf("%d%d%d %*c",&a,&b,&c);
 87         add_edge(a,b,c);
 88         add_edge(b,a,c);
 89     }
 90     dfs(1,-1,0);
 91     rmq_init(2*n-1);
 92     int m;
 93     m=read();
 94     for(int i=0;i<m;++i){
 95         a=read();b=read();
 96         int ans=LCA(a,b);
 97         printf("%lld\n",dis[a]+dis[b]-2*dis[ans]);
 98     }
 99     
100     return 0;
101 }

 

[poj1986]Distance Queries(LCA)

标签:str   span   swap   for   ack   scanf   code   first   namespace   

原文地址:http://www.cnblogs.com/elpsycongroo/p/7469609.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!