链接: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. 201621123034 《Java程序设计》第6周学习总结

    作业06-接口.内部类 1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图或相关笔记,对面向对象思想进行一个总结. 注1:关键词与内容不求多 ...

  2. 七、vue计算属性

    细节流程图 初始化 计算属性的初始化是发生在 Vue 实例初始化阶段的 initState 函数中,执行了 if (opts.computed) initComputed(vm, opts.compu ...

  3. Java8并行流使用注意事项

    对于从事Java开发的童鞋来说,相信对于Java8的并行流并不陌生,没错,我们常常用它来执行并行任务,但是由于并行流(parallel stream)采用的是享线程池,可能会对我们的性能造成严重影响, ...

  4. BZOJ1196 [HNOI2006]公路修建问题 【二分 + Kruskal】

    题目 OI island是一个非常漂亮的岛屿,自开发以来,到这儿来旅游的人很多.然而,由于该岛屿刚刚开发不久,所以那里的交通情况还是很糟糕.所以,OIER Association组织成立了,旨在建立O ...

  5. 【ZBH选讲·树变环】

    [问题描述] 你是能看到第三题的friends呢.——aoao 树是个好东西,删掉树一条边要1的代价,随便再加一条边有1的代价,求最小的代价把树变成环.[输入格式] 第一行一个整数,代表树的点数.接下 ...

  6. 在ESXi使用esxcli命令強制关闭VM

    最近學到一個在VMware ESXi 下面強制關閉一個沒有反應的VM的方法, 一般正常都是使用vSphere Client 去控制VM電源, 但是有時會發生即使用裡面的Power Off 按鈕但是還是 ...

  7. Linux下目录的权限详解

    在Linux文件系统模型中,每个文件都有一组9个权限位用来控制谁能够读写和执行该文件的内容.普通文件大家都了解,这里说说目录的情况. 对于目录来说,执行位的作用是控制能否进入或者通过该目录,而不是控制 ...

  8. tips 前端 移动端 web iscroll 5 自译文档 api速查

    iscroll 可以做的 1,模拟原生的ios 或者android等设备的元素滚动,app里的那种顺滑的滚动,仅仅使用一个轻量的js库实现(甚至更酷炫的视觉感受) 2,手机端流行的下拉刷新,ajax异 ...

  9. [网络流24题] COGS 750 栅格网络流

    750. 栅格网络流 ★★☆   输入文件:flowa.in   输出文件:flowa.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] Bob 觉得一般图的最大流问题太 ...

  10. python module :shelve

    shelve 是一个 key-value 的数据库. 操作方法和字典几乎一致. shelve 模块功能:以 key - value 的方式存储数据. 写数据 >>> import s ...