How far away ?

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 25408    Accepted Submission(s): 10111

Problem Description
There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.
 
Input
First line is a single integer T(T<=10), indicating the number of test cases.
  For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
  Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
 
Output
For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.
 
Sample Input
2
3 2
1 2 10
3 1 15
1 2
2 3

2 2
1 2 100
1 2
2 1

 
Sample Output
10
25
100
100
 
 
题目大意:
给你一棵树,求任两点的距离。
 
这是LCA模板题。
求出两点的公共祖先ancst,然后dis[i,j]=depth[i]+depth[j]-depth[ancst]*2;其中depth是节点在有根树中的深度。
离线tarjan算法。。ctrlc ctrlv一段大佬的解释吧。(来自zhouzhendong的cnblogs)
 

LCA_Tarjan

  TarjanTarjan 算法求 LCA 的时间复杂度为 O(n+q)O(n+q) ,是一种离线算法,要用到并查集。(注:这里的复杂度其实应该不是 O(n+q)O(n+q) ,还需要考虑并查集操作的复杂度 ,但是由于在多数情况下,路径压缩并查集的单次操作复杂度可以看做 O(1)O(1),所以写成了 O(n+q)O(n+q) 。)

  TarjanTarjan 算法基于 dfs ,在 dfs 的过程中,对于每个节点位置的询问做出相应的回答。

  dfs 的过程中,当一棵子树被搜索完成之后,就把他和他的父亲合并成同一集合;在搜索当前子树节点的询问时,如果该询问的另一个节点已经被访问过,那么该编号的询问是被标记了的,于是直接输出当前状态下,另一个节点所在的并查集的祖先;如果另一个节点还没有被访问过,那么就做下标记,继续 dfs 。

  当然,暂时还没那么容易弄懂,所以建议结合下面的例子和标算来看看。

(下面的集合合并都用并查集实现)

  比如:8−1−14−138−1−14−13 ,此时已经完成了对子树 11 的子树 1414 的 dfsdfs 与合并( 1414 子树的集合与 11 所代表的集合合并),如果存在询问 (13,14)(13,14) ,则其 LCA 即 getfather(14)getfather(14) ,即 11 ;如果还存在由节点 1313 与 已经完成搜索的子树中的 节点的询问,那么处理完。然后合并子树 1313 的集合与其父亲 11 当前的集合,回溯到子树 11 ,并深搜完所有 11 的其他未被搜索过的儿子,并完成子树 11 中所有节点的合并,再往上回溯,对节点 11 进行类似的操作即可。

 
大意就是,后根dfs一棵树,如果子树遍历完了,就把它整个加入子树根节点的父亲节点的并查集中。
遇到询问,就判断它的另一点是否已经遍历过了,如果是,就getfather。还是自己画画图,应该不难懂吧。
 
第一次写,比较粗糙,附AC代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
typedef long long LL;
const int MAX_N=;
const int MAX_M=;
const int INF=; struct tedge
{
int to,w,next;
};
tedge edge[MAX_N*+];
int head1[MAX_N+],cnt1; void addedge(int a,int b,int c)
{
edge[cnt1]=(tedge){b,c,head1[a]};head1[a]=cnt1++;
edge[cnt1]=(tedge){a,c,head1[b]};head1[b]=cnt1++;
} struct tquery
{
int to,next;
int index;
};
tquery query[MAX_M*+];
int head2[MAX_N+],cnt2; void addquery(int a,int b,int i)
{
query[cnt2]=(tquery){b,head2[a],i};head2[a]=cnt2++;
query[cnt2]=(tquery){a,head2[b],i};head2[b]=cnt2++;
} int fa[MAX_N]; int getf(int x)
{
if(fa[x]==x)
return x;
else
return fa[x]=getf(fa[x]);
} int vis[MAX_N+];
int depth[MAX_N+];
int ans[MAX_M+]; void LCA(int x,int pa,int dis)
{
for(int i=head1[x];i!=-;i=edge[i].next)
{
int l=edge[i].to;
if(l!=pa)
{
LCA(l,x,dis+edge[i].w);
}
}
depth[x]=dis;
for(int i=head2[x];i!=-;i=query[i].next)
{
int l=query[i].to;
if(vis[l])
{
int ancst=getf(l);
ans[query[i].index]=depth[l]+depth[x]-depth[ancst]*;
//printf("%d %d %d\n",l,x,ancst);
}
}
fa[x]=pa;vis[x]=;
} void init()
{
memset(head1,-,sizeof(head1));cnt1=;
memset(head2,-,sizeof(head2));cnt2=;
memset(vis,,sizeof(vis));
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
int n,m;
scanf("%d%d",&n,&m);
for(int i=,a,b,c;i<=n-;i++)
{
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
}
for(int i=,a,b;i<=m;i++)
{
scanf("%d%d",&a,&b);
addquery(a,b,i);
}
for(int i=;i<=n;i++)
fa[i]=i;
LCA(,-,);
for(int i=;i<=m;i++)
printf("%d\n",ans[i]);
}
return ;
}

hdu 2586 How far away?(LCA模板题+离线tarjan算法)的更多相关文章

  1. hdu 3549 Flow Problem 最大流问题 (模板题)

    Flow Problem Time Limit: 5000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tota ...

  2. 近期公共祖先(LCA)——离线Tarjan算法+并查集优化

    一. 离线Tarjan算法 LCA问题(lowest common ancestors):在一个有根树T中.两个节点和 e&sig=3136f1d5fcf75709d9ac882bd8cfe0 ...

  3. HDU - 2586 How far away ?(LCA模板题)

    HDU - 2586 How far away ? Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & ...

  4. HDU 2586——How far away ?——————【LCA模板题】

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  5. HDU 2602 - Bone Collector - [01背包模板题]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2602 Many years ago , in Teddy’s hometown there was a ...

  6. HDU 2544 最短路 【Dijkstra模板题】

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2544 思路:最短路的模板题 Dijkstra 算法是一种类似于贪心的算法,步骤如下: 1.当到一个点时, ...

  7. 【网络流#2】hdu 1533 - 最小费用最大流模板题

    最小费用最大流,即MCMF(Minimum Cost Maximum Flow)问题 嗯~第一次写费用流题... 这道就是费用流的模板题,找不到更裸的题了 建图:每个m(Man)作为源点,每个H(Ho ...

  8. hdu 1711 Number Sequence(KMP模板题)

    我的第一道KMP. 把两个数列分别当成KMP算法中的模式串和目标串,这道题就变成了一个KMP算法模板题. #include<stdio.h> #include<string.h> ...

  9. HDU 1874 畅通工程续(模板题——Floyd算法)

    题目: 某省自从实行了很多年的畅通工程计划后,终于修建了很多路.不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多.这让行人很困扰 ...

随机推荐

  1. vue中动态加载img

    想实现动态加载图片,当点击“首页”时,图片变色 代码如下: <mt-tabbar v-model="selected" fixed class="border-1p ...

  2. mac如何开启两个vmware虚拟机

    转载链接:https://blog.csdn.net/aifore/article/details/87833088

  3. mysql8.0.13安装、使用教程图解

    mysql8.0.13安装.使用教程图解 MySQL是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Manageme ...

  4. 新闻实时分析系统 基于IDEA环境下的Spark2.X程序开发

    1.Windows开发环境配置与安装 下载IDEA并安装,可以百度一下免费文档. 2.IDEA Maven工程创建与配置 1)配置maven 2)新建Project项目 3)选择maven骨架 4)创 ...

  5. Nginx服务器部署 负载均衡 反向代理

    Nginx服务器部署负载均衡反向代理 LVS Nginx HAProxy的优缺点 三种负载均衡器的优缺点说明如下: LVS的优点: 1.抗负载能力强.工作在第4层仅作分发之用,没有流量的产生,这个特点 ...

  6. 程序员的算法课(16)-B+树在数据库索引中的作用

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/de ...

  7. for源码实现

    for源码实现 我们知道,java的while和for基本上是实现一样的功能,这样会不会有一点缺点,同时java的迭代器显得尤为的麻烦. python的for和while就不同了,在实现迭代的功能的情 ...

  8. 单例模式-python

    单例模式 什么是单例 当实例化多次得到的对象中存放的属性都一样的情况,应该将多个对象指向同一个内存,即同一个实例 有什么优点 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管 ...

  9. jsp 实现查询功能

    要求: 实现查询功能 1.数据库代码 create database mvce; use mvce; create table test2( id int not null identity, tna ...

  10. 转载:不是书评 :《我是一只IT小小鸟》

    本文转载自刘未鹏博客:http://www.mindhacks.cn. 原文地址如下:http://mindhacks.cn/2009/10/05/im-a-tiny-bird-book-review ...