• How far away?


    这个题面真的难受,看了好久才看懂。。。

    题目大意:

    给出一个无环图,求图中任意两点的距离(刚开始还以为是最短路。。。)

    好像没有什么思路,爆搜?肯定超时,那可怎么办?

    其实这道题可以用LCA来解决。。。(要不是前一题做的LCA还真想不到。。。)

    首先,我们还是先找根,但是这道题可能不太好找,所以我们就人为的规定输入的x y中x是爸爸,所以找根就找没有出现在y的位置的结点(就是没有爸爸的节点)

    接着我们预处理出每一个节点向上跳2的i次幂到达的位置,以及它到根节点的路径(显然只有一条,题面里给的),还有它的深度。

    接着我们利用倍增法求出两个点的LCA(具体实现看代码)

    答案就是dis[x]+dis[y]-2*dis[LCA(x,y)]  x,y为询问的两个点(想一想正确性,还是比较显然的)

    最后,附上本题代码:

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #define maxn 40000
      5 using namespace std;
      6 
      7 struct EDGE
      8 {
      9     int nxt,to,v;
     10 };
     11 EDGE edge[maxn*2+5];
     12 int T,n,root,cnt,m;
     13 int head[maxn+5],dep[maxn+5],dis[maxn+5];
     14 int f[maxn+5][25];
     15 bool vis[maxn+5];
     16 
     17 void add(int x,int y,int z)
     18 {
     19     edge[++cnt].to=y;
     20     edge[cnt].v=z;
     21     edge[cnt].nxt=head[x];
     22     head[x]=cnt;
     23 }
     24 void pre_fir(int u,int fa)
     25 {
     26     dep[u]=dep[fa]+1;
     27     for(int i=0; i<=22; i++)
     28     {
     29         f[u][i+1]=f[f[u][i]][i];
     30     }
     31     for(int i=head[u]; i; i=edge[i].nxt)
     32     {
     33         if(edge[i].to==fa)
     34         {
     35             continue;
     36         }
     37         dis[edge[i].to]=dis[u]+edge[i].v;
     38         f[edge[i].to][0]=u;
     39         pre_fir(edge[i].to,u);
     40     }
     41 }
     42 int LCA(int x,int y)
     43 {
     44     if(dep[x]<dep[y])
     45     {
     46         swap(x,y);
     47     }
     48     for(int i=22; i>=0; i--)
     49     {
     50         if(dep[f[x][i]]>=dep[y])
     51         {
     52             x=f[x][i];
     53         }
     54         if(x==y)
     55         {
     56             return x;
     57         }
     58     }
     59     for(int i=22; i>=0; i--)
     60     {
     61         if(f[x][i]!=f[y][i])
     62         {
     63             x=f[x][i];
     64             y=f[y][i];
     65         }
     66     }
     67     return f[x][0];
     68 }
     69 int main()
     70 {
     71     scanf("%d",&T);
     72     while(T--)
     73     {
     74         memset(vis,0,sizeof(vis));
     75         memset(edge,0,sizeof(edge));
     76         memset(f,0,sizeof(f));
     77         memset(dep,0,sizeof(dep));
     78         memset(head,0,sizeof(head));
     79         memset(dis,0,sizeof(dis));
     80         cnt=0;
     81         scanf("%d%d",&n,&m);
     82         for(int i=1; i<=n-1; i++)
     83         {
     84             int x,y,z;
     85             scanf("%d%d%d",&x,&y,&z);
     86             vis[y]=1;
     87             add(x,y,z);
     88             add(y,x,z);
     89         }
     90         for(int i=1; i<=n; i++)
     91         {
     92             if(vis[i]==0)
     93             {
     94                 root=i;
     95                 break;
     96             }
     97         }
     98         pre_fir(root,0);
     99         for(int i=1; i<=m; i++)
    100         {
    101             int a,b;
    102             scanf("%d%d",&a,&b);
    103             printf("%d
    ",dis[a]+dis[b]-2*dis[LCA(a,b)]);
    104         }
    105     }
    106     return 0;
    107 }
  • 相关阅读:
    java连接各种数据库
    java遗传算法
    java中‘==’和’equal‘的区别
    java.net.BindException: Address already in use: JVM_Bind错误,端口设置问题
    Flink学习笔记6 Flink原理-Task(任务)、Operator Chain(算子链)和Slot(资源)
    Flink学习笔记5 Flink原理-资源
    Flink学习笔记4 Flink原理-基础架构
    Flink学习笔记2 CentOS7.5搭建Flink1.6.1分布式集群
    Flink学习笔记1 Flink入门简介
    Dubbo学习笔记12:使用Dubbo中需要注意的一些事情
  • 原文地址:https://www.cnblogs.com/yufenglin/p/10575524.html
Copyright © 2020-2023  润新知