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

LCA模版题。

RMQ+LCA:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <vector> using namespace std;
const int MAXN = 4e4 + ;
typedef pair<int , int>P;
vector <P> G[MAXN];
int dep[MAXN] , dis[MAXN] , par[MAXN][] , ok[MAXN]; void init(int n) {
for(int i = ; i <= n ; i++) {
G[i].clear();
ok[i] = ;
}
} void dfs(int root) {
for(int i = ; i < G[root].size() ; i++) {
dis[G[root][i].first] = dis[root] + G[root][i].second;
dfs(G[root][i].first);
}
} void dfs2(int u , int p , int d) {
dep[u] = d;
par[u][] = p;
for(int i = ; i < G[u].size() ; i++) {
dfs2(G[u][i].first , u , d + );
}
} int lca(int u , int v) {
if(dep[u] < dep[v]) {
swap(u , v);
}
for(int k = ; k < ; k++) {
if((dep[u] - dep[v]) >> k & ) {
u = par[u][k];
}
}
if(u == v)
return u;
for(int k = ; k >= ; k--) {
if(par[u][k] != par[v][k]) {
u = par[u][k];
v = par[v][k];
}
}
return par[u][];
} int main()
{
int n , m , q , v , u , d , root , t;
char op[];
scanf("%d" , &t);
while(t--) {
scanf("%d %d" , &n , &m);
init(n);
root = (n + ) * n / ;
for(int i = ; i < n - ; i++) {
scanf("%d %d %d" , &u , &v , &d);
G[u].push_back(P(v , d));
if(!ok[v]) {
root -= v;
ok[v] = ;
}
}
dfs2(root , - , );
dis[root] = ;
for(int k = ; k < ; k++) {
for(int i = ; i <= n ; i++) {
if(par[i][k] <= ) {
par[i][k + ] = ;
}
else {
par[i][k + ] = par[par[i][k]][k];
}
}
}
dfs(root);
for(int i = ; i < m ; i++) {
scanf("%d %d" , &u , &v);
printf("%d\n" , dis[u] + dis[v] - * dis[lca(u , v)]);
}
}
}

树链剖分的LCA:

 #include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 5e4 + ;
struct data {
int to , next , cost;
}edge[MAXN << ];
int head[MAXN] , cnt;
int par[MAXN] , dep[MAXN] , top[MAXN] , id[MAXN] , dis[MAXN] , size[MAXN] , son[MAXN]; void init() {
memset(head , - , sizeof(head));
cnt = ;
} inline void add(int u , int v , int cost) {
edge[cnt].to = v;
edge[cnt].next = head[u];
edge[cnt].cost = cost;
head[u] = cnt++;
}
//求size , par , son , dep
void dfs_1(int u , int p , int d) {
par[u] = p , size[u] = , son[u] = u , dep[u] = d;
for(int i = head[u] ; ~i ; i = edge[i].next) {
int v = edge[i].to;
if(v == p)
continue;
dis[v] = dis[u] + edge[i].cost; //离根的距离
dfs_1(v , u , d + );
if(size[v] > size[son[u]]) //取重儿子
son[u] = v;
size[u] += size[v];
}
}
//求top , id
void dfs_2(int u , int p , int t) { //p为父节点 t为链的祖先
top[u] = t; //链的祖先
id[u] = ++cnt; //点的顺序
if(son[u] != u) //重儿子优先
dfs_2(son[u] , u , t);
for(int i = head[u] ; ~i ; i = edge[i].next) {
int v = edge[i].to;
if(v == p || v == son[u])
continue;
dfs_2(v , u , v); //树链重新开始
}
}
//树链剖分求lca的复杂度是(nlognlogn),建议用RMQ求lca
int lca(int u , int v) {
int fu = top[u] , fv = top[v];
while(top[u] != top[v]) { //链是否相同,不同就循环
if(dep[fu] < dep[fv]) { //比较两个链的深度
v = par[fv];
fv = top[fv];
}
else {
u = par[fu];
fu = top[u];
}
}
if(dep[u] >= dep[v]) //在相同的链上
return v;
return u;
} int main()
{
int n , q , u , v , cost , x , y , z , t;
scanf("%d" , &t);
while(t--) {
scanf("%d %d" , &n , &q);
init();
for(int i = ; i < n ; ++i) {
scanf("%d %d %d" , &u , &v , &cost);
add(u , v , cost);
add(v , u , cost);
}
cnt = ;
dfs_1( , , );
dfs_2( , , );
while(q--) {
scanf("%d %d" , &x , &y);
int res = (dis[x] + dis[y] - * dis[lca(x , y)]);
printf("%d\n" , res);
}
}
}

HDU 2586 How far away ? (LCA)的更多相关文章

  1. HDU 2586 How far away ? (LCA,Tarjan, spfa)

    题意:给定N个节点一棵树,现在要求询问任意两点之间的简单路径的距离,其实也就是最短路径距离. 析:用LCA问题的Tarjan算法,利用并查集的优越性,产生把所有的点都储存下来,然后把所有的询问也储存下 ...

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

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

  3. hdu 2586 How far away ?倍增LCA

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

  4. HDU 2586 How far away ?【LCA】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=2586 How far away ? Time Limit: 2000/1000 MS (Java/Oth ...

  5. HDU 2586.How far away ?-离线LCA(Tarjan)

    2586.How far away ? 这个题以前写过在线LCA(ST)的,HDU2586.How far away ?-在线LCA(ST) 现在贴一个离线Tarjan版的 代码: //A-HDU25 ...

  6. HDU 2586 How far away ?(LCA在线算法实现)

    http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给出一棵树,求出树上任意两点之间的距离. 思路: 这道题可以利用LCA来做,记录好每个点距离根结点的 ...

  7. HDU 2586 How far away ?(LCA模板 近期公共祖先啊)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the vi ...

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

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给你N个点,M次询问.1~N-1行输入点与点之间的权值,之后M行输入两个点(a,b)之间的最 ...

  9. hdu 2586 How far away ? 带权lca

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

随机推荐

  1. trackr: An AngularJS app with a Java 8 backend – Part I

    该系列文章来自techdev 我想分享在techdev公司开发的项目-trackr-的一些最新的见解.trackr是一个用来跟踪我们的工作时间,创建报告和管理请假的web应用程序.做这个程序的目的有两 ...

  2. POJ 2455 - Secret Milking Machine

    原题地址:http://poj.org/problem?id=2455 题目大意:给出一个N个点的无向图,中间有P条边,要求找出从1到n的T条通路,满足它们之间没有公共边,并使得这些通路中经过的最长的 ...

  3. bzoj2790

    观察这道题,d(a,b) 就是先变成最大公约数然后再变成b 设g[x]表示x的质因数数目,不难得到d(a,b)=g[a/gcd(a,b)]+g[b/gcd(a,b)] 因为g[xy]=g[x]+g[y ...

  4. uva11181Probability|Given

    枚举,条件概率. 2^20次方等于100w,是大约可以没准还能过的. 二进制枚举时,如果买东西的人恰好为r个,设概率为p,就将sum[i]+=p(sum[i]为r个人买东西时第i个人买东西的概率),t ...

  5. 用户输入 i. 检测常用手势(一)

    参考: http://blog.csdn.net/qq418716640/article/details/8508973http://www.cnblogs.com/mengdd/p/3335508. ...

  6. codevs 1135 选择客栈

    这题没什么话说. #include<iostream> #include<cstdio> #include<cstring> #include<algorit ...

  7. Sublime-text markdown with Vim mode and auto preview

    说明 最近看到markdown相关的东西,被其书写方式吸引,其实以前就在找这种类似的工具,但是也没找到,由于习惯了Vim,可Vim不支持markdown预览,这点可能不是很好,于是找到Sublime- ...

  8. LwIP源代码文件目录解析

    1 -- LwIP源代码文件目录 root@motadou:/home/motadou/lwip/lwip-1.4.1# tree . ├── CHANGELOG ├── COPYING ├── do ...

  9. 利用反射自动生成SQL语句(仿Linq)

    转:http://www.cnblogs.com/the7stroke/archive/2012/04/22/2465597.html using System; using System.Colle ...

  10. 使ViewFlipper中的WebView实现手势效果

    使ViewFlipper中的WebView实现手势效果   今天写Blog阅读器的时候遇到了这个问题,把它分享给大家,让同样是新手们少走冤枉路始初写这个功能的时候,用过了好多方法,也耗了不少时间去研究 ...