HDU-2586 (LCA Tarjan & 倍增)_2586 lca-程序员宅基地

技术标签: LCA  

题目连接

题意:

        求一棵树上任意两点的最短距离,n个点,m次询问

数据范围:  

        2 < n < 40000,    2 < m < 200

思路:(Tarjan)

        LCA板子题,需要一个dis [ ] 数组, dis[ x ] 记录一下该点 ( x ) 到父亲节点 ( find(x) ) 的距离 ,当找到一个匹配点 ( to ) 时,两个点的最短距离 = (dis[ x ] + dis[ to ] - dis[ find(x) ] * 2);

补习:点击补习LCA

TarjanAC:

#include<iostream>
#include<cstring>
#include<math.h>
#include<algorithm>
using namespace std;
const int MAXN = 4e4 + 10;
int n, m;
int head[MAXN], head_ask[MAXN], cnt, cnt_ask;
int ans[MAXN], fa[MAXN];
bool vis[MAXN];
int dis[MAXN];	//保存该节点到父亲的距离 
struct Edge {
	int to, next, dis;
	int num;	
}edge[MAXN << 1], ask[MAXN << 1];
void add_edge(int u, int v, int dis){
	edge[++cnt].to = v;
	edge[cnt].next = head[u];
	edge[cnt].dis = dis;
	head[u] = cnt;
}
void add_ask(int u, int v, int num) {
	ask[++cnt_ask].to = v;
	ask[cnt_ask].num = num;
	ask[cnt_ask].next = head_ask[u];
	head_ask[u] = cnt_ask;
}
int find(int x) {
	return fa[x] == x ? x : fa[x] = find(fa[x]);
} 
void init() {
	cnt = 1;
	cnt_ask = 1; 
	memset(vis, 0, sizeof(vis));
	memset(dis, 0, sizeof(dis));
	memset(head,0, sizeof(head));
	memset(head_ask,0, sizeof(head_ask));
	fa[n] = n; 
}
void Tarjan(int x) {
	vis[x] = true;
	for(int i = head[x]; i; i = edge[i].next) {
		int to = edge[i].to; 
		if( !vis[to] ) {
			dis[to] = dis[x] + edge[i].dis; 
			Tarjan(to);
			fa[to] = find(x);
		}
	}
	for(int i = head_ask[x]; i; i = ask[i].next) {
		int to = ask[i].to;
		if (vis[to]) {
			ans[ask[i].num] = dis[to] + dis[x] - dis[find(to)] * 2; 
		}
	}
}
int main () {
	int T;
	cin >> T;
	while(T--) {
		cin >> n >> m;
		int x, y, z;
		init();
		for(int i = 1; i < n; ++i) {
			fa[i] = i;
			cin >> x >> y >> z;
			add_edge(x, y, z);
			add_edge(y, x, z);
		}
		for(int i = 1; i <= m; ++i) {
			cin >> x >> y;
			add_ask(x, y, i);
			add_ask(y, x, i);
		}
		Tarjan(1);
		for(int i = 1; i <= m; ++i) {
			cout << ans[i] << endl;
		}
		
	}
	return 0;
} 

倍增:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 40000 + 10;
int head[MAXN], cnt;
int fa[MAXN][20], depth[MAXN], dis[MAXN];	//记录到根节点的距离 
int n, m;

struct Edge{
	int to, dis, next;
}edge[MAXN << 1];
void add_edge(int u, int v, int dis) {
	edge[++cnt].to = v;
	edge[cnt].dis = dis;
	edge[cnt].next = head[u];
	head[u] = cnt;
}
void init () {
	cnt = 1;
	memset(head, 0, sizeof(head));
	memset(fa, 0, sizeof(fa));
	memset(depth, 0, sizeof(depth));
	memset(dis, 0, sizeof(dis));
}
void DFS(int now, int pre) {
	depth[now] = depth[pre] + 1; 
	fa[now][0] = pre;
	for (int i = 1; (1 << i) <= depth[now]; ++i) {
		fa[now][i] = fa[fa[now][i-1]][i-1];
	}
	for(int i = head[now]; i; i = edge[i].next) {
		int to = edge[i].to;
		if(to != pre){
			dis[to] = dis[now] + edge[i].dis;
			DFS(edge[i].to, now);
		}
			
	}
}
int LCA(int a, int b) {
	if(depth[a] < depth[b]) swap(a, b);
	int dep = depth[a] - depth[b];
	for(int i = 0; (1 << i) <= dep; ++i) {
		if ((1 << i) & dep) 
			a = fa[a][i];
	}
	if(a == b) return a;
	for (int i = log2(depth[a]); i >= 0; --i) {
			//如果父亲不同就向上跳, 如果父亲相同就减小距离再比较,直到不相同在跳。 
		if (fa[a][i] != fa[b][i]) {
			a = fa[a][i];
			b = fa[b][i];	
		}
	}
	return fa[a][0];
}
int main () {
	int T;
	cin >> T;
	while(T--) {
		init(); 
		cin >> n >> m;
		int x, y, z;
		for(int i = 1; i <= n - 1; ++i) {
			cin >> x >> y >> z;
			add_edge(x, y, z);
			add_edge(y, x, z);	
		}
		DFS(1, 0);
		for(int i = 1; i <= m; ++i) {
			cin >> x >> y;
			int temp = LCA(x, y);
			int ans = dis[x] + dis[y] - 2 * dis[temp];
			cout << ans << endl;
		}
	}	
	return 0;
}

 

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

智能推荐

2020-7-8 线程池中execute()⽅法和submit()⽅法的区别?_execute0方法只能执行runnable类型的任务,submit0方法可以执行runnable和-程序员宅基地

文章浏览阅读393次。文章目录线程池中execute()⽅法和submit()⽅法的区别?最简单的回答原理看波继承关系submit()源码如何封装成FutureTask对象execute()源码为什么submit()方法可以有返回结果,就是因为FutureTaskset(result)小结线程池中execute()⽅法和submit()⽅法的区别?最简单的回答 1、execute()只能执行Runnable任务,submit()能执行Callable和Runnable任务; 2、submit()可获取任务执行结果,exe_execute0方法只能执行runnable类型的任务,submit0方法可以执行runnable和callable

a15和a16芯片哪个好 a15和a16性能差距有多少_a15和a16芯片差别大吗-程序员宅基地

文章浏览阅读1.2k次。对于处理器芯片,CPU 能力是人们首先关心的事情,这也是比较A16和A15的前提。与上一代相比,这有助于芯片的性能提升40%。以搭载A16的iPhone14Pro为例,在CPU测试中,得分为246572分,而在GPU基准测试方面,得分则是408723分。但与A15芯片相比,A16芯片的GPU性能提升了28%,同时显存带宽也增加了50%,让图形处理更加流畅。必须提到一些突出的功能,例如在视频录制过程中自动对焦的能力,还有主题和电影模式之间的自动切换等,这些都是将AI技术与最新的A16芯片相结合的完美例子。_a15和a16芯片差别大吗

2023年12.12更新:最新使用cookie自动登录京东并爬取京东网址图书信息python源码!_京东cookie自动登录-程序员宅基地

文章浏览阅读2k次,点赞21次,收藏21次。感谢朋友们阅读,下期再见!!!_京东cookie自动登录

qsub作业一直在排队状态_一些“基本”作业仍在排队中以实现自动化-程序员宅基地

文章浏览阅读1.1k次。qsub作业一直在排队状态The pandemic may speed up job replacement. 大流行可能会加快工作更换速度。 Before Covid-19 swept through America, low-wage workers and activists were battling in the states to raise the minimum wage, of..._qq作业上传视频总在排队中

Hadoop云计算之SSH协议简单介绍-程序员宅基地

文章浏览阅读202次。2019独角兽企业重金招聘Python工程师标准>>> ..._hadoop. 中的ssh 有哪些特点?

java build-id是什么_Java Build.BOOTLOADER属性代码示例-程序员宅基地

文章浏览阅读372次。public String getDeviceInfo() {return "\n" +"Brand:" +Build.BRAND +"\n" +"Manufacturer:" +Build.MANUFACTURER +"\n" +"Product:" +Build.PRODUCT +"\n" +"Board:" +Build.BOARD +"\n" +"Bootloader:" +Build.B..._build.bootloader

随便推点

解决百度网盘(百度云)分享链接不存在失效、分享的文件已经被取消的问题_百度网盘链接不存在解决方法-程序员宅基地

文章浏览阅读2.2w次,点赞2次,收藏6次。解决百度网盘(百度云)分享链接不存在失效、分享的文件已经被取消的问题_百度网盘链接不存在解决方法

永不磨灭的设计模式(有这一篇真够了,拒绝标题党)-程序员宅基地

文章浏览阅读2.3w次,点赞141次,收藏912次。在IT这个行业,技术日新月异。有可能你今年刚弄懂一个编程框架,明年它就不流行了,无怪乎有些无节操的IT从业人员去GitBub上用汉语提Issue:“求你别更新了,实在学不动了”。对于这种行为我只能说,太jb不要脸了…然而即使在易变的IT世界也有很多几乎不变的知识,他们晦涩而重要,默默的将程序员划分...._永不磨灭的设计模式

栈与C++中的std::stack详解(多图超详细)_stack出栈-程序员宅基地

文章浏览阅读874次。栈(stack)什么是栈?栈的基本操作和应用入栈(push)出栈(pop)入栈和出栈的复杂度和应用场景类模板std::satck形参T和Container成员函数元素访问栈的容量栈的修改用法示例_stack出栈

R ggplot2 图例-改图例背景颜色、大小_ggplot改变图例形状大小-程序员宅基地

文章浏览阅读4.4w次,点赞31次,收藏132次。改 图例背景颜色改 图例大小改 图例符号颜色第一部分1.1 图例背景颜色1.2 代码和语法base + theme( legend.background = element_rect( fill = "lightblue", #填充色 colour = "black", #框线色 size = 1.5 ) ) #线条宽度语法在theme主题系统..._ggplot改变图例形状大小

python读取文件夹内容(os.listdir()方法)_files = os.listdir-程序员宅基地

文章浏览阅读1.1w次,点赞7次,收藏19次。python os.listdir() 方法一般用于导出指定路径下的文件或文件夹目录。当输入的“要打开”的是文件夹(直接是文件夹的名字,没有后缀),获得的是文件夹中的文件名称列表(按字母表顺序排序)代码:import os path = 'C:\\Users\\DELL\\Desktop\\hello' #打开桌面位置处的文件夹hello,注意格式\\result=os.listdi..._files = os.listdir

win10快速访问的文件夹无法删除的解决方法_automaticdestinations文件夹里的文件删不掉-程序员宅基地

文章浏览阅读2.5w次,点赞23次,收藏17次。最近遇到快速访问的文件夹右键无法取消固定,不管怎么试都删不掉,最后我尝试了把快速访问恢复默认,解决了这个问题具体方法:找到快速访问的存储目录是这里,大家可以应对自己所用环境修改用户名:C:\Users\用户名\AppData\Roaming\Microsoft\Windows\Recent\AutomaticDestinations删除路径中的所有文件,快速访问就会重置到最初的状态!在..._automaticdestinations文件夹里的文件删不掉

推荐文章

热门文章

相关标签