文章目录
题目描述
实验室里原先有一台电脑(编号为1),最近氪金带师咕咕东又为实验室购置了N-1台电脑,编号为2到N。每台电脑都用网线连接到一台先前安装的电脑上。但是咕咕东担心网速太慢,他希望知道第i台电脑到其他电脑的最大网线长度,但是可怜的咕咕东在不久前刚刚遭受了宇宙射线的降智打击,请你帮帮他。
提示: 样例输入对应这个图,从这个图中你可以看出,距离1号电脑最远的电脑是4号电脑,他们之间的距离是3。 4号电脑与5号电脑都是距离2号电脑最远的点,故其答案是2。5号电脑距离3号电脑最远,故对于3号电脑来说它的答案是3。同样的我们可以计算出4号电脑和5号电脑的答案是4.
输入
输入文件包含多组测试数据。对于每组测试数据,第一行一个整数N (N<=10000),接下来有N-1行,每一行两个数,对于第i行的两个数,它们表示与i号电脑连接的电脑编号以及它们之间网线的长度。网线的总长度不会超过10^9,每个数之间用一个空格隔开。
输出
对于每组测试数据输出N行,第i行表示i号电脑的答案 (1<=i<=N).
样例输入
5
1 1
2 1
3 1
1 1
样例输出
3
2
3
4
4
思路
综述
这道题主要考察了一个新的知识:树的直径:
树的直径被定义为树中任意两点之间距离的最大值
参考:图的存储和图的遍历
做法
1、从树的任意一点开始遍历这棵树。找到的距离这个点最远的点是树的直径的一个点;
2、从找到的这个点,开始遍历这个树,再找到的另一个点是该树的直径的另一个点;
本题
任取一点 1
dfs一次找到点v1
dfs两次找到点v2,同时标记了其他所有点到v1的距离
dfs三次从v2开始,标记了其他所有点到v1的距离
最后输出某个点到v1v2的最大距离即可
过程
Step1:初始化
采用前向星方式,不再赘述
参考:图的存储和图的遍历
const int maxn = 1e4 + 5;
struct Edge {
int u, v, w, nxt;
}Edges[20020];
int head[maxn], tot;
void addEdge(int u, int v, int w) {
Edges[tot].u = u;
Edges[tot].v = v;
Edges[tot].w = w;
Edges[tot].nxt = head[u];
head[u] = tot;
tot++;
}
Step2:从1开始dfs
深度优先搜索
Step2.1:到达一点,标记
vis1[u] = true;
Step2.2:遍历该点的所有邻接边
for (int i = head[u]; i != -1; i = Edges[i].nxt) {
//找到一个未标记的点
if (!vis1[Edges[i].v] ) {
//标记
vis1[Edges[i].v] = true;
//记录距离
path1[Edges[i].v] = path1[u] + Edges[i].w;
//记录最大距离
if (maxpath1 < path1[Edges[i].v]) {
v1 = Edges[i].v;
maxpath1 = path1[Edges[i].v];
}
//继续进行
dfs1(Edges[i].v);
}
}
Step3:从v1开始dfs
与找v1极为类似
void dfs2(int u) {
vis2[u] = true;
for (int i = head[u]; i != -1; i = Edges[i].nxt) {
if (!vis2[Edges[i].v]) {
vis2[Edges[i].v] = true;
path2[Edges[i].v] = path2[u] + Edges[i].w;
if (maxpath2 < path2[Edges[i].v]) {
v2 = Edges[i].v;
maxpath2 = path2[Edges[i].v];
}
dfs2(Edges[i].v);
}
}
}
Step4:从v2开始dfs
与找v1极为类似
void dfs3(int u) {
vis3[u] = true;
for (int i = head[u]; i != -1; i = Edges[i].nxt) {
if (!vis3[Edges[i].v]) {
vis3[Edges[i].v] = true;
path3[Edges[i].v] = path3[u] + Edges[i].w;
dfs3(Edges[i].v);
}
}
}
总结
这道题考察三个方面:
1、普通的dfs或者bfs遍历算法
2、如何确定树的直径问题:两次遍历
3、多组数据之间是否合理的进行初始化
void init() {
for (int i = 0; i < maxn; i++) {
path1[i] = 0;
path2[i] = 0;
path3[i] = 0;
vis1[i] = false;
vis2[i] = false;
vis3[i] = false;
head[i] = -1;
}
maxpath1 = 0;
maxpath2 = 0;
tot=0;
}
代码
在上文中有详细注释,故不再赘述
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int N;
const int maxn = 1e4 + 5;
struct Edge {
int u, v, w, nxt;
}Edges[20020];
int head[maxn], tot;
void addEdge(int u, int v, int w) {
Edges[tot].u = u;
Edges[tot].v = v;
Edges[tot].w = w;
Edges[tot].nxt = head[u];
head[u] = tot;
tot++;
}
int path1[maxn];
int path2[maxn];
int path3[maxn];
bool vis1[maxn];
bool vis2[maxn];
bool vis3[maxn];
int v1;
int v2;
int maxpath1 = 0;
int maxpath2 = 0;
void dfs1(int u) {
vis1[u] = true;
for (int i = head[u]; i != -1; i = Edges[i].nxt) {
if (!vis1[Edges[i].v] ) {
vis1[Edges[i].v] = true;
path1[Edges[i].v] = path1[u] + Edges[i].w;
if (maxpath1 < path1[Edges[i].v]) {
v1 = Edges[i].v;
maxpath1 = path1[Edges[i].v];
}
dfs1(Edges[i].v);
}
}
}
void dfs2(int u) {
vis2[u] = true;
for (int i = head[u]; i != -1; i = Edges[i].nxt) {
if (!vis2[Edges[i].v]) {
vis2[Edges[i].v] = true;
path2[Edges[i].v] = path2[u] + Edges[i].w;
if (maxpath2 < path2[Edges[i].v]) {
v2 = Edges[i].v;
maxpath2 = path2[Edges[i].v];
}
dfs2(Edges[i].v);
}
}
}
void dfs3(int u) {
vis3[u] = true;
for (int i = head[u]; i != -1; i = Edges[i].nxt) {
if (!vis3[Edges[i].v]) {
vis3[Edges[i].v] = true;
path3[Edges[i].v] = path3[u] + Edges[i].w;
dfs3(Edges[i].v);
}
}
}
void init() {
for (int i = 0; i < maxn; i++) {
path1[i] = 0;
path2[i] = 0;
path3[i] = 0;
vis1[i] = false;
vis2[i] = false;
vis3[i] = false;
head[i] = -1;
}
maxpath1 = 0;
maxpath2 = 0;
tot=0;
}
int main() {
while (cin >> N) {
init();
for (int i = 2; i <= N; i++) {
int a, b;
scanf("%d%d", &a, &b);
addEdge(a, i, b);
addEdge(i, a, b);
}
dfs1(1);
dfs2(v1);
dfs3(v2);
for (int i = 1; i <= N; i++) {
cout << max(path3[i], path2[i]) <<endl;
//cout << path2[i] << " " << path3[i] << endl;
}
}
}