Week6--作业 -- A -- 氪金带东[树直径问题]

题目描述

实验室里原先有一台电脑(编号为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:遍历该点的所有邻接边

扫描二维码关注公众号,回复: 10399744 查看本文章
	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;
		}
	}
		
	
}
发布了29 篇原创文章 · 获赞 14 · 访问量 1248

猜你喜欢

转载自blog.csdn.net/weixin_44552961/article/details/105247635
今日推荐