HDU - 2196 Computer (树的直径)

题目链接

题意:给出一个n,表示有n台电脑,之后给出n-1行,每行一个v,w(第i行的v,w表示i和v点之间有一条长度为w的线)要求输出第1到n台计算机能传送数据的最远距离?

题解:我们可以知道该题是在变向的求树的直径,先取任意一点dfs得到最远的一个点作为树的直径的一个端点X,再以该端点X进行dfs得到另一个端点Y(端点X、Y的距离也就是树的直径),最后再以端点Y进行dfs即可得到每个点到端点Y的距离,那么题目要求的数据最大传送距离即为该点到树的直径端点X、Y的最远距离.

代码如下:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn = 1e5 + 500;
struct edge
{
	int v, w;
	edge(int vv = 0, int ww = 0) :v(vv), w(ww) {}
};
int w[3][maxn];
vector<edge>e[maxn];
void dfs(int pos, int prt, int sta, int ww)//pos->当前点,prt->父节点,sta->存储指向,ww->距离
{
	w[sta][pos] = ww;
	for (int i = 0; i < e[pos].size(); i++)
	{
		if (e[pos][i].v == prt)continue;
		dfs(e[pos][i].v, pos, sta, ww + e[pos][i].w);
	}
}
int main()
{
	int n;
	while (~scanf("%d", &n))
	{
		for (int i = 1; i <= n; i++)//清空
			e[i].clear();
		for (int i = 2; i <= n; i++)//输入
		{
			int v, ww;
			scanf("%d%d", &v, &ww);
			e[i].push_back(edge(v, ww));
			e[v].push_back(edge(i, ww));
		}
		dfs(1, -1, 0, 0);//跑出以1为根到所有点的距离存入w[0][]中
		int pos = 1;
		for (int i = 2; i <= n; i++)
			if (w[0][pos] < w[0][i])  pos = i;   //获得距离初始根1最远的点记录下pos
		dfs(pos, -1, 1, 0); //在以最远的那个点pos为根跑一边dfs,获得该根到所有点的距离存入w[1][]中
		pos = 1;
		for (int i = 2; i <= n; i++)
			if (w[1][pos] < w[1][i])pos = i;   //重新获得距离上个根最远的位置pos
		dfs(pos, -1, 2, 0);  //在以新的根跑一边dfs,获得它到所有点的距离w[2][]
		for (int i = 1; i <= n; i++)
			printf("%d\n", max(w[1][i], w[2][i]));//因此,每个点到距离他最远的点就是到树的直径2端点的最大距离
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41156591/article/details/81813040