最近公共祖先(LCA),树上差分,树的直径总结

2024-08-24 12:28

本文主要是介绍最近公共祖先(LCA),树上差分,树的直径总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近也是一不小心就学到了树论,这方面确实太不行了,也该开始学习一下了,那么话不多说,进入今日份的树论学习,直接开冲

最近公共祖先(LCA)——倍增思想(可以结合我之前写的ST表学习)

 

我们来看什么是最近公共祖先,对于9和8来讲,其最近公共祖先为6,对于3和7来讲,其最近公共祖先为5,那么我们去求最近公共祖先总共要有两步

第一步就是深搜,我们这一遍的深搜主要是为了去统计每一个点的深度,以及往上走2的n次方步的能够达到的父亲结点吗


void dfs(int v,int father)
{dep[v]=dep[father]+1;f[v][0]=father;for(int i=1;i<20;i++){f[v][i]=f[f[v][i-1]][i-1];}for(int u:e[v]){if(u!=father){dfs(u,v);}}
}

 第二步就是去寻找公共祖先,首先我们要去确保u节点的深度一定要小于v节点,这样可以确保每次调用这个lca函数的时候不会出错,然后就是将u节点和v节点调到同一个深度,如果u节点和v节点相同,就说明v节点是u节点的祖先节点,直接返回v节点即可,如果不相同则就将这个两个节点一起向上推,直到这两个点相同

int lca(int u,int v)
{if(dep[u]<dep[v]){swap(u,v);}for(int i=19;i>=0;i--){if(dep[f[u][i]]>=dep[v]){u=f[u][i];}}if(u==v)return v;for(int i=19;i>=0;i--){if(f[u][i]!=f[v][i]){u=f[u][i];v=f[v][i];}}return f[u][0];
}

树上差分

树上差分分为点差分边差分

 

比如说我们想要将一条边上的权值都加1,那么我们需要在两个节点处先将这个1加上去,然后在最近公共祖先处-1,其父辈也要-1; 

 

 

 

 树的直径

树的直径有两种求法一种是树上dp去求树的直径,另一种就是两次dfs去求

树上dp

void dp(int x,int fa){//x表示当前的节点,fa是x
的父节点for(int i=head[x];i;i=next[i]){//前向星int y=ver[i],z=w[i];//y是下一个节点,z是x,y的距离,在本题就是1if(y==fa)continue;//只用遍历一次,不用回到父节点dp(y);ans=max(ans,dis[x]+dis[y]+z);dis[x]=max(dis[x],dis[y]+z);//dis[x]表示从节点x出发走到以x为根的子树//能够到的最远距离}
}

两次dfs

void dfs1(int x,int fa){if(deep[x]>zj){zj=deep[x];num=x;}for(int i=head[x];i;i=next[i]){int y=ver[i];if(y==fa)continue;deep[y]=deep[x]+1;dfs1(y,x);}
}
void dfs2(int x,int fa){if(deep[x]>zj){zj=deep[x];num=x;}for(int i=head[x];i;i=next[i]){int y=ver[i];if(y==fa)continue;deep[y]=deep[x]+1;f[y]=x;//记录路径,表示y的父节点为xdfs2(y,x);}
}

这篇关于最近公共祖先(LCA),树上差分,树的直径总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1102475

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

zoj3820(树的直径的应用)

题意:在一颗树上找两个点,使得所有点到选择与其更近的一个点的距离的最大值最小。 思路:如果是选择一个点的话,那么点就是直径的中点。现在考虑两个点的情况,先求树的直径,再把直径最中间的边去掉,再求剩下的两个子树中直径的中点。 代码如下: #include <stdio.h>#include <string.h>#include <algorithm>#include <map>#

poj1330(LCA最近公共祖先)

题意:求最近公共祖先 思路:之前学习了树链剖分,然后我就用树链剖分的一小部分知识就可以解这个题目了,记录每个结点的fa和depth。然后查找时,每次将depth大的结点往上走直到x = y。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring>

poj 3159 (spfa差分约束最短路) poj 1201

poj 3159: 题意: 每次给出b比a多不多于c个糖果,求n最多比1多多少个糖果。 解析: 差分约束。 这个博客讲差分约束讲的比较好: http://www.cnblogs.com/void/archive/2011/08/26/2153928.html 套个spfa。 代码: #include <iostream>#include <cstdio>#i

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

poj 3169 spfa 差分约束

题意: 给n只牛,这些牛有些关系。 ml个关系:fr 与 to 牛间的距离要小于等于 cost。 md个关系:fr 与 to 牛间的距离要大于等于 cost。 隐含关系: d[ i ] <= d[ i + 1 ] 解析: 用以上关系建图,求1-n间最短路即可。 新学了一种建图的方法。。。。。。 代码: #include <iostream>#include

二分最大匹配总结

HDU 2444  黑白染色 ,二分图判定 const int maxn = 208 ;vector<int> g[maxn] ;int n ;bool vis[maxn] ;int match[maxn] ;;int color[maxn] ;int setcolor(int u , int c){color[u] = c ;for(vector<int>::iter

整数Hash散列总结

方法:    step1  :线性探测  step2 散列   当 h(k)位置已经存储有元素的时候,依次探查(h(k)+i) mod S, i=1,2,3…,直到找到空的存储单元为止。其中,S为 数组长度。 HDU 1496   a*x1^2+b*x2^2+c*x3^2+d*x4^2=0 。 x在 [-100,100] 解的个数  const int MaxN = 3000

状态dp总结

zoj 3631  N 个数中选若干数和(只能选一次)<=M 的最大值 const int Max_N = 38 ;int a[1<<16] , b[1<<16] , x[Max_N] , e[Max_N] ;void GetNum(int g[] , int n , int s[] , int &m){ int i , j , t ;m = 0 ;for(i = 0 ;