程序设计思维 A - 氪金带东(链式前向星、DFS)

题目

实验室里原先有一台电脑(编号为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

思路

一、链式前向星
图有三种存储方式:邻接矩阵邻接表链式前向星
链式前向星与邻接表相类似。链式前向星由数组Head和结构体数组Edges构成,如图:
在这里插入图片描述
二、解题
由题可知,连接的网路呈一个树状的结构,树的直径的定义为:

树中任意两点之间距离的最大值

如图,从V1到V2的路径是树的直径。
在这里插入图片描述
首先选择某一点X,进行DFS搜索,直到最深的点,可以证明,这个点一定是树的直径的两端的其中一点,如图中的V2
在这里插入图片描述
再从V2进行DFS搜索,直到最深的点,则这个点一定V1
所以,在一棵树中,对于某一点X,离这个X最远的点一定要么是V1,要么是V2
算法如下:
① 选定某一点(如1号点),进行DFS搜索,找到最深的点,设该点为V1
② 从V1开始,进行DFS搜索,找到最深的点,设该点为V2。在进行DFS搜索时,计算每个点到V1的距离,将距离存放在数组dist1中。
③ 再从V2开始,进行DFS搜索。在进行DFS搜索时,计算每个点到V2的距离,将距离存放在数组dist2中。
④ 计算每个点到其他点的最大距离:i号点到其他点的最大距离为MAX(dist1[i], dist2[i])。

代码

#include <iostream>
#include <algorithm>
#define MAX 100100
// 由题意,这是一棵树,故有MAX个顶点,MAX-1条边

using namespace std;

int N;

// Edge[0]不用
struct Edge {
	int to, weight, next;
}Edges[MAX];

int head[MAX];
bool visit[MAX];
int dist1[MAX];
int dist2[MAX];

int edgeNum;
int remote;

void addEdge(int u, int v, int w)
{
	Edges[edgeNum].to = v;
	Edges[edgeNum].weight = w;
	Edges[edgeNum].next = head[u];
	head[u] = edgeNum;
	edgeNum++;
}

// DFS算法找最远的点
void DFS(int sorce, int length, int* dist)
{
	dist[sorce] = length;
	visit[sorce] = true;

	if (dist[remote] < dist[sorce]) remote = sorce;

	for (int i = head[sorce]; i != 0; i = Edges[i].next) {
		if (!visit[Edges[i].to]) {
			visit[Edges[i].to] = 1;
			DFS(Edges[i].to, length + Edges[i].weight, dist);
		}
	}
}

int main()
{
	while (cin >> N) {
		memset(head, 0, sizeof(head));
		edgeNum = 1;
		for (int i = 2; i <= N; i++)
		{
			int v, w;
			cin >> v >> w;
			addEdge(i, v, w);
			addEdge(v, i, w);
		}

		remote = 1;

		memset(visit, false, sizeof(visit));
		DFS(remote, 0, dist1);

		memset(visit, false, sizeof(visit));
		DFS(remote, 0, dist1);

		memset(visit, false, sizeof(visit));
		DFS(remote, 0, dist2);

		for (int i = 1; i <= N; i++)
			cout << max(dist1[i], dist2[i]) << endl;
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值