题目描述
实验室里原先有一台电脑(编号为1),最近氪金带师咕咕东又为实验室购置了N-1台电脑,编号为2到N。每台电脑都用网线连接到一台先前安装的电脑上。但是咕咕东担心网速太慢,他希望知道第i台电脑到其他电脑的最大网线长度,但是可怜的咕咕东在不久前刚刚遭受了宇宙射线的降智打击,请你帮帮他。
Input
输入文件包含多组测试数据。对于每组测试数据,第一行一个整数N (N<=10000),接下来有N-1行,每一行两个数,对于第i行的两个数,它们表示与i号电脑连接的电脑编号以及它们之间网线的长度。网线的总长度不会超过10^9,每个数之间用一个空格隔开。
Output
对于每组测试数据输出N行,第i行表示i号电脑的答案 (1<=i<=N).
Sample Input
5
1 1
2 1
3 1
1 1
Sample Output
3
2
3
4
4
解题思路
首先看到题,可以抽象为一个图的问题(每台电脑是点,每根网线是边),并且是一个无向图。为了表示边和点的关系,需要采用邻接矩阵,邻接链表的方式来存储。但是这里有一种新的简便的方法——链式前向星,即通过数组的方式来表示链表。每一个数组元素对应一个点,其中存放的是邻接边的序号,然后根据此序号访问下一条边,直到序号为-1(结尾标志)。
想清楚用什么表示以后,需要确定计算的方法。要计算每一个点到其它点的最远距离,首先的想法是依次遍历每个点,用bfs的方式求出最远的距离。但这样时间复杂度太高,每个店都需要计算一次最远距离。
一种新的做法是利用图的直径——相距最远的两个点之间的距离。图中任意点的最远距离一定是到这两个点其中之一的距离。那么问题就简单了,先根据任一点找到最远距离,然后再根据找到的这个点遍历得到直径的另一个端点,再用这个端点遍历图的每一个顶点,最后比较直径两个端点到达每个点的距离,取出大的那一条边,即是该点的最大距离。
这样只用了三次遍历即可得到结果,大大降低复杂度。这里使用的遍历方式是dfs。
代码
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN=10010;
int head[MAXN],vis[MAXN],ans[MAXN],ans1[MAXN];
int tot=0