标签:maxx 1078 int 最大值 up 蓝桥 d2 DP d1
题目大意: 求一个树上,直径上的所有的点
数据范围:节点n 1<=n<=2e5
范围很大 要求时间复杂度控制在 lnn 以内
分析:
这是一个树形DP,基于树的直径,求树所有直径上的点
整体思路:
1、先通过树形dp求出每个点往下走的最大长度和次大长度,并且更新整棵树的最大路径maxx
2、往下走最大值(第一步已求) + 往上走最大值 == maxx,即在直径上
这个题的难点就是:
首先要理解为什么一个节点既要往上求,又要往下求?
因为第一次dfs时候,回溯时候,是从下往上的,先求下面的点,再上边的
借助y总画的图容易理解
还有就是理解那三个数组:d1往下最大值 d2往下的次大值 up是往上的最大值(实际上就是配合p数组,求最大值)
还有就是p数组的理解: p[u]=j :从u下去是j 。
比如一个点 i 往下的最大值和次大值是确定的,往上不确定,往上是递归,这里的往上也不是严格意义的往上,是相较与上次递归向下而言的,也有可能向下。
这个p数组就是为了防止向下时候最大值算两边,如果是最大值就取次小值。反正这个up值是一直取最大的。
看代码:
#include <bits/stdc++.h> using namespace std; const int N=2e5+10,M=2*N; int n; int h[N],e[M],ne[M],idx; int d1[N],d2[N],p[N],up[N]; int maxx; void add(int a,int b) { e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void dfs1(int u,int father) { for(int i=h[u];~i;i=ne[i]) { int j=e[i]; if(j!=father) { dfs1(j,u); int d=d1[j]+1; if(d>d1[u]) { d2[u]=d1[u]; d1[u]=d; p[u]=j; }else if(d>d2[u]) { d2[u]=d; } } } maxx=max(maxx,d1[u]+d2[u]); } void dfs2(int u,int father) { for(int i=h[u];~i;i=ne[i]) { int j=e[i]; if(j!=father) { up[j]=up[u]+1; if(p[u]==j) { up[j]=max(up[j],d2[u]+1); }else { up[j]=max(up[j],d1[u]+1); } dfs2(j,u); } } } int main() { memset(h,-1,sizeof (h)); cin>>n; for(int i=0;i<n;i++) { int a,b; scanf("%d%d",&a,&b); add(a,b); add(b,a); } dfs1(0,-1); dfs2(0,-1); for(int i=0;i<n;i++) { int a[3]={d1[i],d2[i],up[i]}; sort(a,a+3); if(a[2]+a[1]==maxx) { cout<<i<<endl; } } return 0; }
END!!!
标签:maxx,1078,int,最大值,up,蓝桥,d2,DP,d1 来源: https://www.cnblogs.com/qinmo/p/16093576.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。