HDU 2196 Computer

1.题目描述:点击打开链接

2.解题思路:本题是经典的树形dp问题:求一棵树上每个结点的最远点的距离。这个问题可以用如下的方法解决:首先随意选择一个点作为根结点进行dfs,求出所有点到根结点的最远距离的那个结点,假设是p,接下来以p树根,再进行一次dfs,求出最远的点q,那么p-q就是树上的直径。并且可以证明,所有点的最远点要么是p,要么q。详细的证明可以参考如下链接,这样整个问题就可以在O(N)时间内解决。

证明链接:点击打开链接

3.代码:

#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cctype>
#include<list>
#include<complex>
#include<functional>
using namespace std;

#define me(s) memset(s,0,sizeof(s))
#define rep(i,n) for(int i=0;i<(n);i++)
#define pb push_back
typedef long long ll;
typedef pair <int,int> P;


const int N = 20000 + 10;

struct Edge
{
	int to;
	int dist;
	int next;
};

Edge e[N];
int head[N];
int d1[N], d2[N];
int cnt, n;

void init()
{
    memset(head,-1,sizeof(head));
    cnt=0;
}
void addedge(int u, int v, int dist)
{
	e[cnt]=Edge{v,dist,head[u]};
	head[u] = cnt++;
}

void dfs(int u, int fa, int dist, int*d)
{
	d[u] = dist;
	for (int i = head[u]; ~i; i = e[i].next)
	{
		int v = e[i].to;
		if (v != fa)
			dfs(v, u, dist+e[i].dist, d);
	}
}

int main()
{

	while (~scanf("%d", &n))
	{
	    init();
		int v, dist;
		for (int i = 2; i<=n; i++)
		{
			scanf("%d%d", &v, &dist);
			addedge(i, v, dist);
			addedge(v, i, dist);
		}
		dfs(1, 0, 0, d1);
		int p=1, q=1; //p是直径的一端
		int mx = 0;
		for (int i = 1; i <= n; i++)
			if (mx<d1[i])
			{
				mx = d1[i]; p = i;
			}
		dfs(p, 0, 0, d1);
		mx = 0;
		for (int i = 1; i <= n; i++)
			if (mx<d1[i])
			{
				mx = d1[i]; q = i; //q是直径的另一端
			}
		dfs(q, 0, 0, d2);
		for (int i = 1; i <= n; i++)
			printf("%d\n",max(d1[i],d2[i]));
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值