最一开始想到的暴力解法,直接维护一个二维数组,求出所有点之间的距离,找出最大值。但是发现n最大是10^5,时间复杂度只能是O(n),也就是说,在有限的遍历中就能找出那个最大值。因此需要知道一个树中的性质。 从a点找出一个最远点b,从b再出发,找出最远点c(很容易知道bc的距离是大于等于ab的,c点就是a点时取等号,a在bc这条路上的时候取大于号)那么bc就是最大距离。证明如下: 假设存在一条边的距离大于bc,那么首先,这条边的起点和终点绝对不是a或b或c,设为mn。 假设m与a是相通的,那么m,n,a之间不可能构成环,所以只有2种情况。此时a->m->n或者m->n->a的距离就大于m->n,不正确。也有可能是m->a->n 或者n->a->m这条路线,如果是这样的话。因为an和am这两条路的大小都小于ab(ab为a引出去的最长距离),所以ab,ac,am,an的大小关系就是 ab > an > ac 并且 ab > am > ac 并且 am+an > ab+ac,但是此时 b引出去的最长距离就不是b->a->c(此处有个问题,b引出的最长距离未必经过a,可以是另外一条支路,也就是abc公用了一个根,此时把根理解为a,一样得出结论)就是b->a->n或者m,又不正确。 因此证明了bc这条边就是最长的距离。
class Solution { public: /** * @param n: The number of nodes * @param starts: One point of the edge * @param ends: Another point of the edge * @param lens: The length of the edge * @return: Return the length of longest path on the tree. */
void dfs(vector<vector<int>> cost,const int tar, int & _max, int & END) { int n = cost.size(),top = -1, j, s[10007]; vector<int> visited(n, 0); visited[tar] = 1; s[++top] = tar; int v; while (top != -1) { v = s[top]; for (j = 0; j < n; j++) { if (visited[j] == 0 && cost[v][j] != 0) { visited[j] = 1; s[++top] = j; if (cost[tar][j] == 0) { cost[j][tar] = cost[tar][j] = cost[tar][v] + cost[v][j]; if (_max < cost[tar][j]) { _max = cost[tar][j]; END = j; } } break; } } if (j == n) top--; } }
int longestPath(int n, vector<int> &starts, vector<int> &ends, vector<int> &lens) { // Write your code here vector<vector<int>> cost; cost.resize(n); for (int i = 0; i < n; i++) cost[i].resize(n); for (int i = 0; i < n-1; i++) { int start = starts[i], end = ends[i], len = lens[i]; cost[start][end] = len; cost[end][start] = len; } int _max = 0, END = 0; dfs(cost, 0,_max, END); _max = 0; dfs(cost, END,_max, END); return _max; } };
public class Solution { /** * @param n: The number of nodes * @param starts: One point of the edge * @param ends: Another point of the edge * @param lens: The length of the edge * @return: Return the length of longest path on the tree. */ class TreeNode { int val; Map<TreeNode, Integer> neighbors;
public TreeNode(int val) { this.val = val; neighbors = new HashMap<>(); } }
class Pair implements Comparable<Pair> { TreeNode node; int val;
public Pair(TreeNode node, int val) { this.node = node; this.val = val; }
@Override public int compareTo(Pair other) { return this.val - other.val; } }
public int longestPath(int n, int[] starts, int[] ends, int[] lens) { if (n <= 1) { return 0; }
Map<Integer, TreeNode> map = new HashMap<>(); for (int i = 0; i < starts.length; i++) { if (!map.containsKey(starts[i])) { TreeNode newNode = new TreeNode(starts[i]); map.put(starts[i], newNode); } if (!map.containsKey(ends[i])) { TreeNode newNode = new TreeNode(ends[i]); map.put(ends[i], newNode); } TreeNode node1 = map.get(starts[i]); TreeNode node2 = map.get(ends[i]); node1.neighbors.put(node2, lens[i]); node2.neighbors.put(node1, lens[i]); } TreeNode root = map.get(0);
Pair p = bfsHelper(n, root); return bfsHelper(n, p.node).val; }
private Pair bfsHelper(int n, TreeNode node) { Pair res = new Pair(null, -1); boolean[] visited = new boolean[n]; visited[node.val] = true;
PriorityQueue<Pair> pq = new PriorityQueue<>(); pq.offer(new Pair(node, 0));
while (!pq.isEmpty()) { Pair curt = pq.poll(); res = curt; for (Map.Entry<TreeNode, Integer> entry : curt.node.neighbors.entrySet()) { if (visited[entry.getKey().val]) { continue; } visited[entry.getKey().val] = true; pq.offer(new Pair(entry.getKey(), curt.val + entry.getValue())); } }
return res; } }
如果有大神能指正我的代码的错误。非常感谢!
-------------end of file
thanks for reading-------------