题意:给出一个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;
}