链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586

【题意】

给出一个N 个和N-1条边的连通图,询问任意两点间的距离。N<=40000 。

【分析】

点太多了,用最短路算法来求超时。只够求一个点的单源最短路,而且不能用O(n2)的算法。正确的做法就是求出两点的最近公共祖先,利用点v到树的根节点距离dis[v]来换算。设要求的两点分别为u和v, 那么u和v的距离d=dis[u]+dis[v]-2*dis[LCA(u,v)] 。

现在还有一个问题就是输入是一个图,并不是一棵树,怎么有根节点?怎么确定父子关系?
     这个挺好办的,随便选一个点当根节点,从这个节点开始分层遍历,这样就有树的结构了。求dis数组我原先是用单源最短路来求的,不过仔细想下,因为原图就是一棵树,从根节点到任意点的路径是唯一的,于是就可以用递推的方式求的,在分层遍历中计算就好了。遍历递归的层数有点多,可能会爆栈。

这里我使用LCA转RMQ的方法来求的。

【代码】

 #pragma comment(linker, "/STACK:1024000000,1024000000") //扩栈
#include <stdio.h>
#include <string.h>
#include <vector>
#include <cmath>
using namespace std;
int n,m;
struct edge
{
int d,v,next;
edge(){}
edge(int _d,int _v,int _next)
{
d=_d;v=_v;next=_next;
}
}data[];
int map[];
int pool;
void addedge(int s,int e,int v)
{
int t=map[s];
data[pool++]=edge(e,v,t);
map[s]=pool-;
}
vector<int> f;
vector<int> b;
bool ifv[];
int pos[];
int dis[];
void dfs(int cur,int c)
{
if (cur< || cur>=n) return;
ifv[cur]=true;
pos[cur]=(int)f.size();
f.push_back(cur);
b.push_back(c);
int p=map[cur];
while (p!=-)
{
if (!ifv[data[p].d])
{
dis[data[p].d]=dis[cur]+data[p].v;
dfs(data[p].d,c+);
f.push_back(cur);
b.push_back(c);
}
p=data[p].next;
}
}
int rmq[][];
void makermq(int n,int bitn)
{
for (int i=; i<n; ++i)
rmq[i][]=b[i];
for (int j=; j<bitn; ++j)
for (int i=; i<n; ++i)
{
if (i+(<<(j-))>=n) break;
rmq[i][j]=min(rmq[i][j-],rmq[i+(<<(j-))][j-]);
}
}
int query(int s,int e)
{
int k=(int)((log(e-s+1.0)/log(2.0)));
return min(rmq[s][k],rmq[e-(<<k)+][k]);
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
pool=;
f.clear();
b.clear();
memset(map,-,sizeof map);
memset(ifv,,sizeof ifv);
scanf("%d%d",&n,&m);
int s,e,v;
for (int i=;i<n-;++i)
{
scanf("%d%d%d",&s,&e,&v);
addedge(s-,e-,v);
addedge(e-,s-,v);
}
dis[]=;
dfs(,);
makermq(b.size(),(int)(log((double)b.size())/log(2.0)));
for (int i=;i<m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
--u;--v;
int s=pos[u];
int e=pos[v];
if (s>e) swap(s,e);
int k=query(s,e);
k=f[k];
int ans=dis[u]+dis[v]-*dis[k];
printf("%d\n",ans);
}
}
}

HDU 2586 How far away? LCA 转化成RMQ的更多相关文章

  1. hdu 2586(最近公共祖先LCA)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路:在求解最近公共祖先的问题上,用到的是Tarjan的思想,从根结点开始形成一棵深搜树,非常好 ...

  2. HDU 2586 How far away(LCA+邻接表)

    How far away &题解: 和上篇是一样的题,这用的是lca方法做的, 不知道为什么,把数组开到80000 就a了 >_< 哈 我现在知道为什么了,因为我的rmq数组没有乘 ...

  3. HDU 2586 倍增法求lca

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

  4. TTTTTTTTTTTTTTTTT HDU 2586 How far away LCA的离线算法 Tarjan

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

  5. LCA转换成RMQ

    LCA(Lowest Common Ancestor 最近公共祖先)定义如下:在一棵树中两个节点的LCA为这两个节点所有的公共祖先中深度最大的节点. 比如这棵树 结点5和6的LCA是2,12和7的LC ...

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

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

  7. hdu 2586 How far away ?倍增LCA

    hdu 2586 How far away ?倍增LCA 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路: 针对询问次数多的时候,采取倍增 ...

  8. LCA(最近公共祖先)--tarjan离线算法 hdu 2586

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

  9. hdu 2586(裸LCA)

    传送门 题意: 某村庄有n个小屋,n-1条道路连接着n个小屋(无环),求村庄A到村庄B的距离,要求是经过任一村庄不超过一次. 题解: 求出 lca = LCA(u,v) , 然后答案便是dist[u] ...

随机推荐

  1. nodejs下载图片到本地,根据百度图片查找相应的图片,通过nodejs保存到本地文件夹

    根据百度图片查找相应的图片:输入图片关键字,输入图片数量(默认是30条),通过nodejs将批量保存图片到本地文件夹. 代码已上传到github上:代码github的地址 下载后进去back-end: ...

  2. PHP遍历数组的几种方法

      这三种方法中效率最高的是使用foreach语句遍历数组.从PHP4开始就引入了foreach结构,是PHP中专门为遍历数组而设计的语句,推荐大家使用.先分别介绍这几种方法     PHP中遍历数组 ...

  3. 软工实践Alpha冲刺(5/10)

    队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 已经解决登录注册等基本功能的界面. 完成了主界面的基本布局 ...

  4. URAL 1942 Attack at the Orbit

    B - Attack at the Orbit Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & % ...

  5. nyoj 题目44 子串和

    子串和 时间限制:5000 ms  |  内存限制:65535 KB 难度:3   描述 给定一整型数列{a1,a2...,an},找出连续非空子串{ax,ax+1,...,ay},使得该子序列的和最 ...

  6. 201621123033 《Java程序设计》第1周学习总结

    1. 本周学习总结 · jdk.jre.jvm的含义及相关概念(具体见下文回答) · 会使用记事本及简单编辑器编写Java程序,理解javac和java命令的含义(具体见下文回答) · java与C语 ...

  7. hadoop生态圈列式存储系统--kudu介绍及安装配置

    介绍 Kudu 是一个针对 Apache Hadoop 平台而开发的列式存储管理器.Kudu 共享 Hadoop 生态系统应用的常见技术特性: 它在 commodity hardware(商品硬件)上 ...

  8. CentOS7 安装 webgoat 7.1 简介

    CentOS7 安装 webgoat 7.1 简介 webgoat 所需文件准备: 操作系统版本:CentOS 7.3 1: 在Linux上安装Openjdk >= 1.8 2: 上传文件至 L ...

  9. [hdu] 5696 区间的价值 || 序列分治

    原题 我们定义"区间的价值"为一段区间的最大值*最小值. 一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1). 求长度分别为1-n的区间的最大价值. 保证数据随机 因 ...

  10. Google C++编程风格指南 - 中文版

    Google C++编程风格指南 - 中文版 from http://code.google.com/p/google-styleguide/ 版本: 3.133原作者: Benjy Weinberg ...