填坑行动7-树的直径及求出树的直径路径
树的直径的定义
树的直径是树里面最长的一条链。树的直径不仅仅只有一条。
求树的直径有两种方法:搜索和树形DP。这里主要介绍树形DP。
求出树的直径的长度
方法一、dfs大法
这里不做过多的介绍,主要是记录下一某个点为端点的最长路径和次长路径就可以了。
方法二、树形DP
这里令是一棵以为根节点的子树的深度。
如果节点的孩子为那么,以为节点的这棵树的直径就是,其中是边权,无边权的时候直接当成。当然,我们在搜索的时候需要枚举,也就是在dfs的时候要对每个节点进行判断,一般在回溯的时候进行判断。
代码如下:
#include<cstdio>//无权树 #include<cstring> #define max(a,b) ((a)>(b)?(a):(b)) #define maxn 300039 using namespace std; int head[maxn],to[maxn],nex[maxn],k; #define add(x,y); nex[++k]=head[x];\ to[k]=y;\ head[x]=k; int n,m,x,y,z; int maxx; int f[maxn]; void dfs(int num,int pre){ f[num]=0; for(int i=head[num];i!=-1;i=nex[i]) if(to[i]!=pre){ dfs(to[i],num); maxx=max(maxx,f[num]+f[to[i]]+1); f[num]=max(f[to[i]]+1,f[num]); } return; } int main(){ memset(head,-1,sizeof(head)); scanf("%d",&n); for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); add(x,y); add(y,x); } maxx=-10000000000; dfs(1,0); printf("%d",maxx); return 0; }
求出树的直径路径
方法一、dfs大法
只要记录下搜索的路径即可
方法二、树形DP
发现网上关于树形DP求直径路径的很少,这里就来一发。
我们令来表示节点中第长边的下一个端点,往往只需要记录和的值就可以了。
我们在更新的时候就可以更新,只需要把原来的改成 就可以了。当然,在更新的时候,我们还要更新一个变量,表示这棵树的直径是从为中间的端点,相当于树的重心。如果要输出这个树的直径,我们可以先输出,然后从左边开始,输出,接着是,直到输到底为止,然后输出,接着是,但是要注意不是。
代码如下:
#include<cstdio> //求直径路径 #include<cstring>//DP #define max(a,b) ((a)>(b)?(a):(b)) #define maxn 200039 using namespace std; int head[maxn],to[maxn],nex[maxn],v[maxn],k; #define add(x,y,z); nex[++k]=head[x];\ to[k]=y;\ head[x]=k;\ v[k]=z; int n,m,x,y,z; int maxx; int f[maxn],g[maxn][3],node; void dfs(int num,int pre){ f[num]=0; int max1,max2; max1=max2=0; for(int i=head[num];i!=-1;i=nex[i]) if(to[i]!=pre){ dfs(to[i],num); if(f[to[i]]+v[i]>max1){ max2=max1; g[num][2]=g[num][1]; max1=f[to[i]]+v[i]; g[num][1]=to[i]; } else if(f[to[i]]+v[i]>max2){ max2=f[to[i]]+v[i]; g[num][2]=to[i]; } f[num]=max(f[to[i]]+v[i],f[num]); } if(max1+max2>maxx){ maxx=max1+max2; node=num; } return; } int main(){ memset(head,-1,sizeof(head)); scanf("%d",&n); for(int i=1;i<n;i++){ scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } maxx=-10000000000; dfs(1,0); int i; //printf("%d",node); i=node; while(i){ printf("%d ",i); i=g[i][1]; } i=g[node][2]; while(i){ printf("%d ",i); i=g[i][1]; } printf("\n%d",maxx); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具