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

How far away?

时间:2019-03-22 00:34:08      阅读:122      评论:0      收藏:0      [点我收藏+]

标签:\n   return   tin   开始   continue   roo   head   --   iostream   

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

题目大意:

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

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

其实这道题可以用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\n",dis[a]+dis[b]-2*dis[LCA(a,b)]);
104         }
105     }
106     return 0;
107 }

 

How far away?

标签:\n   return   tin   开始   continue   roo   head   --   iostream   

原文地址:https://www.cnblogs.com/yufenglin/p/10575524.html

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