How far away?(hdu2586-LCA模板)【尚未完成】

原题链接

题目描述

在这里插入图片描述

输入描述

在这里插入图片描述

输出描述

在这里插入图片描述

输入样例

2
3 2
1 2 10
3 1 15
1 2
2 3

2 2
1 2 100
1 2
2 1

输出样例

10
25
100
100

典型的 LCA 模板题,实质就是求出两点间的最近公共祖先,若最近公共祖先为两点其中一点,则最短距离为另一结点到最近公共祖先的距离;反之则为两点到最近公共祖先距离之和。

本题的朴素做法是将两个结点跳到同一深度后,每次同时向上跳一个深度进行比对,相同则说明该结点即为最近公共祖先,否则继续往上跳直到符合要求为止。但由于该做法的时间复杂度男默女泪,因此可考虑类似于二分原理的倍增。

由于最近公共祖先的所有祖先结点都是所求两点的公共祖先,因此可判断两点倍增后的结点是否相同(此处倍增从更靠近根节点的祖先结点开始,直到父结点)。若相同,则说明最近公共祖先即为该点或深度更深的点;若不同,则更新该结点为其祖先结点,并重复以上步骤。

因此,本题需要用 dfs 预处理出每个结点的深度从而得到每个结点对应的倍增后的祖先,以及初始两结点间的深度差(需要将两结点处理至同一深度)。

核心代码【尚未完成】

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
vector<int> g[N];
int father[N][40]={
    
    0};
int depth[N]={
    
    0};
int n,m;
bool visit[N]={
    
    false};
int root;

void dfs(int u){
    
    
	int i;
	visit[u]=true;
	for(int i=0;i<g[u].size();i++){
    
    
		int v=g[u][i];
		if(!visit[v]){
    
    
			depth[v]=depth[u]+1;
			dfs(v);
		}
	}
}

void bz(){
    
    
	int i,j;
	for(j=1;j<=30;j++)
		for(i=1;i<=n;i++)
			father[i][j]=father[father[i][j-1]][j-1];
}

int LCA(int u,int v){
    
    
	if(depth[u]<depth[v])
		swap(u,v);
	
	int dc=depth[u]-depth[v];
	int i;
	for(int i=0;i<30;i++)
		if((1<<i)&dc)
			u=father[u][i];
	
	if(u==v)
		return u;
	
	for(i=29;i>=0;i--)
		if(father[u][i]!=father[v][i]){
    
    
			u=father[u][i];
			v=father[v][i];
		}
	
	u=father[u][0];
	return u;
}

猜你喜欢

转载自blog.csdn.net/laysan/article/details/119920789