博客
关于我
【Lintcode】291. Second Diameter
阅读量:188 次
发布时间:2019-02-28

本文共 3196 字,大约阅读时间需要 10 分钟。

题目地址:

给定一棵树型的无向带权图,求其次大直径(即所有两点距离 d ( v 1 , v 2 ) d(v_1,v_2) d(v1,v2)里第二大的,相等的距离也要参与计数)。

先求最大直径(第一直径)的两个端点 v 1 v_1 v1 v 2 v_2 v2,则 max ⁡ u ≠ v 2 d ( v 1 , u ) \max_{u\ne v_2} d(v_1, u) maxu=v2d(v1,u) max ⁡ u ≠ v 1 d ( v 2 , u ) \max_{u\ne v_1} d(v_2, u) maxu=v1d(v2,u)的最大值即为所求。而求最远点距离可以用BFS来做(主要是为了防止DFS爆栈)。

算法正确性证明:

首先,参考可知从任意点出发找到的最远距离的点一定是直径的一个端点,那么第二直径一定有某个点不是 v 1 v_1 v1或者 v 2 v_2 v2,但是第二直径的非第一直径的端点的那个端点出发,最远距离一定是到达了直径的某个端点的,换言之,第二直径可以从第一直径的某个端点出发,搜到最远的非 v 1 v_1 v1或者 v 2 v_2 v2的点的距离,就是第二直径长度。

代码如下:

import java.util.*;public class Solution {           private long res;        /**     * @param edge: edge[i][0] [1] [2]  start point,end point,value     * @return: return the second diameter length of the tree     */    public long getSecondDiameter(int[][] edge) {           // write your code here        // 顶点数是边数加1        int n = edge.length + 1;        Map
> graph = buildGraph(edge); // 先找到直径的两个端点 int far1 = bfs(0, graph, -1, new boolean[n]); int far2 = bfs(far1, graph, -1, new boolean[n]); // 然后分别从两个端点出发,计算除去另一个端点的情况下的最远距离 bfs(far1, graph, far2, new boolean[n]); bfs(far2, graph, far1, new boolean[n]); return res; } // 返回与v离得最远的,但不是u的点的编号。同时当u不是直径端点的时候,更新res private int bfs(int v, Map
> graph, int u, boolean[] visited) { Queue
queue = new LinkedList<>(); queue.offer(new long[]{ v, 0}); visited[v] = true; // farV存离v最远的点(可能要排除u) int farV = v; // 存v离farV的距离 long farDis = 0; while (!queue.isEmpty()) { int size = queue.size(); for (int i = 0; i < size; i++) { long[] cur = queue.poll(); int nextV = (int) cur[0]; if (graph.containsKey(nextV)) { for (int[] next : graph.get(nextV)) { // 忽略掉第一直径的端点 if (next[0] != u && !visited[next[0]]) { // 为了找到离v最远的点,如果找到更远距离了,则更新距离和遇到的点 if (next[1] + cur[1] > farDis) { farDis = next[1] + cur[1]; farV = next[0]; } visited[next[0]] = true; queue.offer(new long[]{ next[0], next[1] + cur[1]}); } } } } } // 只有其中一个点不是第一直径的时候,才能更新答案 if (u != -1) { res = Math.max(res, farDis); } return farV; } // 邻接表建图,value的[0]存的是与key连接的顶点编号,[1]存的是边长 private Map
> buildGraph(int[][] edges) { Map
> graph = new HashMap<>(); for (int[] edge : edges) { graph.putIfAbsent(edge[0], new ArrayList<>()); graph.get(edge[0]).add(new int[]{ edge[1], edge[2]}); graph.putIfAbsent(edge[1], new ArrayList<>()); graph.get(edge[1]).add(new int[]{ edge[0], edge[2]}); } return graph; }}

时空复杂度 O ( n ) O(n) O(n) n n n是树的顶点个数。

转载地址:http://adjs.baihongyu.com/

你可能感兴趣的文章
netcat的端口转发功能的实现
查看>>
NetCore 上传,断点续传,可支持流上传
查看>>
Netcraft报告: let's encrypt和Comodo发布成千上万的网络钓鱼证书
查看>>
Netem功能
查看>>
netfilter应用场景
查看>>
Netflix:当你按下“播放”的时候发生了什么?
查看>>
Netflix推荐系统:从评分预测到消费者法则
查看>>
netframework 4.0内置处理JSON对象
查看>>
Netgear WN604 downloadFile.php 信息泄露漏洞复现(CVE-2024-6646)
查看>>
Netgear wndr3700v2 路由器刷OpenWrt打造全能服务器(十一)备份
查看>>
netlink2.6.32内核实现源码
查看>>
netmiko 自动判断设备类型python_Python netmiko模块的使用
查看>>
NetMizer 日志管理系统 多处前台RCE漏洞复现
查看>>
NetMizer-日志管理系统 dologin.php SQL注入漏洞复现(XVE-2024-37672)
查看>>
Netpas:不一样的SD-WAN+ 保障网络通讯品质
查看>>
netron工具简单使用
查看>>
NetScaler MPX Gateway Configuration
查看>>
NetScaler的常用配置
查看>>
netsh advfirewall
查看>>
NETSH WINSOCK RESET这条命令的含义和作用?
查看>>