“科林明伦杯”哈尔滨理工大学第十届程序设计竞赛Part2(A——重新定义的树的直径)
A. 点对最大值
题意:
给定一棵既有点权又有边权的树,将两点之间的权值重新定义为路径上的边权和两点的点权之和。问两点之间的最大权值。
思路:
相当于是 重新定义了树的直径,让你求解。
对于无边权的树的直径的求解:(BFS或DFS)
1.任取一点作为起点,找到距离该点最远的一个点x
2.找到距离x最远的一个点y
3.x和y之间的路径就是一条直径
关于有边权的树的直径的求解:(树形DP)
我们可以根据每一条路径上的高度最高的点来把所有路径分类,在这类内部求max,再在每一类里取max.
现在的问题就转化成了如何求出以节点x为最高点的路径的长度的最大值。
很容易可以知道,该最大值就是从节点x往下走,每一个子节点方向的路径的最大值与次大值之和。
int dfs(int u,int fa){ int dist=0,d1=0,d2=0; for(int i=h[u];~i;i=ne[i]){ int j=e[i]; if(j==fa) continue; int d=dfs(j,u)+w[i]; dist=max(dist,d); if(d>=d1) d2=d1,d1=d; else if(d>d2) d2=d; } ans=max(ans,d1+d2); return dist; }
关于既有边权又有点权的树的直径的求解(本题):
我们可以用dp[i]表示以i为最高点(根节点)时,只包含一个端点的权值和最大的链的的权值。
因为边权有负值,所以应当设为-inf;
代码:
https://ac.nowcoder.com/acm/contest/view-submission?submissionId=43888545
参考博客: