題目描述
實驗室裏原先有一臺電腦(編號爲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;
}
}
}