HDU 2586 LCA
题目大意:
多点形成一棵树,树上边有权值,给出一堆询问,求出每个询问中两个点的距离
这里求两个点的距离可以直接理解为求出两个点到根节点的权值之和,再减去2倍的最近公共祖先到根节点的距离
这是自己第一道lca题目
学习了两种方法
第一种在ST算法,利用RMQ思想预处理
/*在线ST算法*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 40010 int first[N] , k; struct Edge{
int x , y , w , next;
Edge(){}
Edge(int x , int y , int w , int next):x(x),y(y),w(w),next(next){}
}e[N<<]; void add_edge(int x , int y , int w)
{
e[k] = Edge(x , y , w , first[x]);
first[x] = k++;
}
int dp[N<<][];
int id[N<<] , dep[N<<] , dis[N] , No[N] , dfs_clock;
void dfs(int u , int f , int d)
{
id[++dfs_clock] = u , No[u] = dfs_clock , dep[dfs_clock] = d;
for(int i=first[u] ; ~i ; i=e[i].next){
int v = e[i].y;
if(v == f) continue;
dis[v] = dis[u]+e[i].w;
dfs(v , u , d+);
id[++dfs_clock] = u , dep[dfs_clock] = d;
}
} void ST(int n)
{
for(int i= ; i<=n ; i++) dp[i][] = i;
for(int j= ; (<<j)<=n ; j++){
for(int i= ; i+(<<j)-<=n ; i++){
int a = dp[i][j-] , b = dp[i+(<<(j-))][j-];
dp[i][j] = dep[a]<dep[b]?a:b;
}
}
} int RMQ(int l , int r)
{
int k=;
while((<<(k+))<=r-l+) k++;
int a = dp[l][k] , b = dp[r-(<<k)+][k];
return dep[a]<dep[b]?a:b;
} int LCA(int u , int v)
{
int x = No[u] , y = No[v];
if(x>y) swap(x , y);
return id[RMQ(x , y)];
} int n , m; int main()
{
// freopen("in.txt" , "r" , stdin);
int T , x , y , w;
scanf("%d" , &T);
while(T--)
{
scanf("%d%d" , &n , &m);
memset(first , - , sizeof(first));
k = ;
for(int i= ; i<n ; i++){
scanf("%d%d%d" , &x , &y , &w);
add_edge(x , y , w);
add_edge(y , x , w);
}
dfs_clock = ;
dis[] = ;
dfs( , , );
ST(*n-);
while(m--){
scanf("%d%d" , &x , &y);
int anc = LCA(x , y);
printf("%d\n" , dis[x]-*dis[anc]+dis[y]);
}
}
return ;
}
ST算法
第二种是离线的Tarjan算法,利用并查集的思想解决
/*在线ST算法*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 40010
#define M 205
int first[N] , k; struct Edge{
int x , y , w , next;
Edge(){}
Edge(int x , int y , int w , int next):x(x),y(y),w(w),next(next){}
}e[N<<]; int _first[N] , _k; struct Que{
int v , lca , next;
Que(){}
Que(int v , int lca , int next):v(v),lca(lca),next(next){}
}eq[M<<]; void add_edge(int x , int y , int w)
{
e[k] = Edge(x , y , w , first[x]);
first[x] = k++;
} void add_que_edge(int x , int y)
{
eq[_k] = Que(y , , _first[x]);
_first[x] = _k++;
} int fa[N] , dis[N];
bool vis[N];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} void tarjan(int u)
{
vis[u] = true , fa[u] = u;
for(int i=first[u] ; ~i ; i=e[i].next){
int v = e[i].y;
if(vis[v]) continue;
dis[v] = dis[u]+e[i].w;
tarjan(v);
fa[v] = u;
}
for(int i=_first[u] ; ~i ; i=eq[i].next){
int v = eq[i].v;
if(vis[v]) eq[i].lca = eq[i^].lca = find(eq[i].v);
}
}
int n , m; int main()
{
// freopen("in.txt" , "r" , stdin);
int T , x , y , w;
scanf("%d" , &T);
while(T--)
{
scanf("%d%d" , &n , &m);
memset(first , - , sizeof(first));
k = ;
for(int i= ; i<n ; i++){
scanf("%d%d%d" , &x , &y , &w);
add_edge(x , y , w);
add_edge(y , x , w);
}
memset(_first , - , sizeof(_first));
_k = ;
for(int i= ; i<m ; i++){
scanf("%d%d" , &x , &y);
add_que_edge(x , y);
add_que_edge(y , x);
}
memset(vis , , sizeof(vis));
tarjan();
for(int i= ; i<m* ; i+=){
int lca = eq[i].lca;
printf("%d\n" , dis[eq[i].v]-*dis[lca]+dis[eq[i^].v]);
}
}
return ;
}
Tarjan算法
HDU 2586 LCA的更多相关文章
- HDU 2586 (LCA模板题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2586 题目大意:在一个无向树上,求一条链权和. 解题思路: 0 | 1 / \ 2 3 ...
- [hdu 2586]lca模板题(在线+离线两种版本)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 在线版本: 在线方法的思路很简单,就是倍增.一遍dfs得到每个节点的父亲,以及每个点的深度.然后 ...
- HDU 2586 ( LCA/tarjan算法模板)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:n个村庄构成一棵无根树,q次询问,求任意两个村庄之间的最短距离 思路:求出两个村庄的LCA,d ...
- hdu 2586(LCA在线ST)
How far away ? Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total Submission(s): A ...
- hdu - 2586 (LCA板子题)
传送门 (这次的英文题面要比上一个容易看多了) (英语蒟蒻的卑微) 又是一个很裸的LCA题 (显然,这次不太容易打暴力咧) (但听说还是有大佬用dfs直接a掉了) 正好 趁这个机会复习一下LCA 这里 ...
- hdu 2586 lca在线算法(朴素算法)
#include<stdio.h> #include<string.h>//用c/c++会爆栈,用g++ac #define inf 0x3fffffff #define N ...
- HDU 2586 How far away ? (LCA)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 LCA模版题. RMQ+LCA: #include <iostream> #incl ...
- HDU - 2586 How far away ?(LCA模板题)
HDU - 2586 How far away ? Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & ...
- hdu 2586 How far away ?倍增LCA
hdu 2586 How far away ?倍增LCA 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路: 针对询问次数多的时候,采取倍增 ...
随机推荐
- ctrl+enter提交留言
<!DOCTYPE html><html lang="zh-CN"><head> <meta charset="UTF-8&qu ...
- asmca无法创建ASM磁盘
现象 grid用户使用asmca无法创建asm磁盘,如下图 分析 如图所示,报错说是 Grid Infrastructure 出了问题.那么 Grid Infrastructure 是什么 ? 在安装 ...
- LTIB常用命令2
LTIB 编译配置选项 根据说明文档,ltib 可以通过以下的命令配置: * <verbatim># ./ltib</verbatim> 安装后第一次运行,采 ...
- eclipse+adt+sdk开发环境搭配
1.开发环境配置 http://www.mamicode.com/info-detail-516839.html
- ctrl + d 在phpstorm 和 eclipse 中的不同含义
Ctrl + d 在phpstrom是复制一行,非常的方便,但是eclipse中却是删除一行,非常的特别.感觉上,phpstorm更注重鼠标,但eclipse貌似更多鼠标和键盘的操作, 默认情况下[p ...
- C++/C#中堆栈、对象内存模型、深浅拷贝、Array.Clone方法
转载自:http://blog.csdn.net/jarvischu/article/details/6425534 目录 1. C++/C#中对象内存模型................. ...
- python 基础学习(字典对象,set对象)
1.dict 字典对象 a.定义对象 d={'a':14,'b':12}b.通过key获取value d['a'] 方法1.判断key是否存在 if 'a' in d: d['a']方法2:通过用ge ...
- Java学习之约瑟夫环的两中处理方法
package day_2; import java.util.Scanner; /** * @author Administrator * 约瑟夫环问题: 设编号为 1,2,3,....n的N个人围 ...
- hdu ---(4517)小小明系列故事——游戏的烦恼(Dp)
小小明系列故事——游戏的烦恼 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)To ...
- android.support.v4.app.Fragment和android.app.Fragment区别
1.最低支持版本不同 android.app.Fragment 兼容的最低版本是android:minSdkVersion="11" 即3.0版 android.support.v ...