• hdu2586 LCA


    题意:有 n 个点,由 n-1 条无向边相连,构成了一棵树,每一条边都有各自的权值,然后有m个询问,分别是询问某两点之间的距离。

    在树上求两点的路径和,由于树上的路径是确定的,只要求两点分别到他们的LCA的路径和,就是求 两点到根节点的路径和 减去 他们LCA到根节点的路径和的两倍 。

    在线倍增:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 const int maxn=4e4+5;
     7 const int maxm=8e4+5;
     8 const int maxl=20;        //总点数的log范围,一般会开稍大一点
     9 
    10 int fa[maxl][maxn],dep[maxn],dis[maxn];        //fa[i][j]是j点向上(不包括自己)2**i 层的父节点,dep是某个点的深度(根节点深度为0),dis是节点到根节点的距离
    11 int head[maxn],point[maxm],nxt[maxm],val[maxm],size,n;
    12 
    13 void init(){
    14     size=0;
    15     memset(head,-1,sizeof(head));
    16 }
    17 
    18 void add(int a,int b,int v){
    19     point[size]=b;
    20     val[size]=v;
    21     nxt[size]=head[a];
    22     head[a]=size++;
    23     point[size]=a;
    24     val[size]=v;
    25     nxt[size]=head[b];
    26     head[b]=size++;
    27 }
    28 
    29 void Dfs(int s,int pre,int d){        //传入当前节点标号,父亲节点标号,以及当前深度
    30     fa[0][s]=pre;                    //当前节点的上一层父节点是传入的父节点标号
    31     dep[s]=d;
    32     for(int i=head[s];~i;i=nxt[i]){
    33         int j=point[i];
    34         if(j==pre)continue;
    35         dis[j]=dis[s]+val[i];
    36         Dfs(j,s,d+1);
    37     }
    38 }
    39 
    40 void Pre(){
    41     dis[1]=0;
    42     Dfs(1,-1,0);
    43     for(int k=0;k+1<maxl;++k){        //类似RMQ的做法,处理出点向上2的幂次的祖先。
    44         for(int v=1;v<=n;++v){
    45             if(fa[k][v]<0)fa[k+1][v]=-1;
    46             else fa[k+1][v]=fa[k][fa[k][v]];    //处理出两倍距离的祖先
    47         }
    48     }
    49 }
    50 
    51 int Lca(int u,int v){
    52     if(dep[u]>dep[v])swap(u,v);        //定u为靠近根的点
    53     for(int k=maxl-1;k>=0;--k){
    54         if((dep[v]-dep[u])&(1<<k))    //根据层数差值的二进制向上找v的父亲
    55             v=fa[k][v];
    56     }
    57     if(u==v)return u;                //u为v的根
    58     for(int k=maxl-1;k>=0;--k){
    59         if(fa[k][u]!=fa[k][v]){        //保持在相等层数,同时上爬寻找相同父节点
    60             u=fa[k][u];
    61             v=fa[k][v];
    62         }
    63     }
    64     return fa[0][u];                //u离lca只差一步
    65 }
    66 
    67 int main(){
    68     int T;
    69     scanf("%d",&T);
    70     while(T--){
    71         int m;
    72         scanf("%d%d",&n,&m);
    73         init();
    74         for(int i=1;i<n;++i){
    75             int a,b,v;
    76             scanf("%d%d%d",&a,&b,&v);
    77             add(a,b,v);
    78         }
    79         Pre();
    80         while(m--){
    81             int a,b;
    82             scanf("%d%d",&a,&b);
    83             int num=Lca(a,b);
    84             printf("%d
    ",dis[a]+dis[b]-2*dis[num]);
    85         }
    86     }
    87     return 0;
    88 }
    View Code

    离线Tarjan:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<vector>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 const int maxn=4e4+5;
     8 const int maxm=8e4+5;
     9 const int maxq=205;
    10 
    11 int n;
    12 int head[maxn],nxt[maxm],point[maxm],val[maxm],size;
    13 int vis[maxn],fa[maxn],dis[maxn];
    14 int ans[maxq];
    15 vector<pair<int,int> >v[maxn];
    16 
    17 void init(){
    18     memset(head,-1,sizeof(head));
    19     size=0;
    20     memset(vis,0,sizeof(vis));
    21     for(int i=1;i<=n;++i){
    22         v[i].clear();
    23         fa[i]=i;
    24     }
    25     dis[1]=0;
    26 }
    27 
    28 void add(int a,int b,int v){
    29     point[size]=b;
    30     val[size]=v;
    31     nxt[size]=head[a];
    32     head[a]=size++;
    33     point[size]=a;
    34     val[size]=v;
    35     nxt[size]=head[b];
    36     head[b]=size++;
    37 }
    38 
    39 int find(int x){
    40     return x==fa[x]?x:fa[x]=find(fa[x]);
    41 }
    42 
    43 void Tarjan(int s,int pre){
    44     for(int i=head[s];~i;i=nxt[i]){
    45         int j=point[i];
    46         if(j!=pre){
    47             dis[j]=dis[s]+val[i];
    48             Tarjan(j,s);
    49             int x=find(j),y=find(s);
    50             if(x!=y)fa[x]=y;
    51         }
    52     }
    53     vis[s]=1;
    54     for(int i=0;i<v[s].size();++i){
    55         int j=v[s][i].first;
    56         if(vis[j]){
    57             int lca=find(j);
    58             int id=v[s][i].second;
    59             ans[id]=dis[s]+dis[j]-2*dis[lca];
    60         }
    61     }
    62 }
    63 
    64 int main(){
    65     int T;
    66     scanf("%d",&T);
    67     while(T--){
    68         int k;
    69         scanf("%d%d",&n,&k);
    70         init();
    71         for(int i=1;i<n;++i){
    72             int a,b,v;
    73             scanf("%d%d%d",&a,&b,&v);
    74             add(a,b,v);
    75         }
    76         for(int i=1;i<=k;++i){
    77             int a,b;
    78             scanf("%d%d",&a,&b);
    79             v[a].push_back(make_pair(b,i));
    80             v[b].push_back(make_pair(a,i));
    81         }
    82         Tarjan(1,0);
    83         for(int i=1;i<=k;++i)printf("%d
    ",ans[i]);
    84     }
    85 }
    View Code
  • 相关阅读:
    Http的请求协议请求行介绍
    Http概述
    服务器返回的14种常见HTTP状态码
    Tomcat发布项目
    Tomca的启动与关闭
    TomCat概述
    PrepareStatement
    JDBC的工具类
    JDBC的异常处理方式
    ResultSet
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4827353.html
Copyright © 2020-2023  润新知