HDU-2196 Computer (树形DP)

题目大意:在一棵带边权的有根树中,对于每个点,找出它与离它最远的那个点的之间的距离。

题目分析:对于一个点,离它最远的点只有两种情况,一是它到叶子节点的最远距离,一是与它父亲的距离加上他的父亲到叶子节点的最远距离。因为它的父亲到叶子的最远距离的那条路径可能恰好经过它自己,所以还要求出每个点到叶子节点的次大距离。

代码如下:

# include<iostream>
# include<cstdio>
# include<vector>
# include<cstring>
# include<algorithm>
using namespace std;

const int N=10010;

struct Edge
{
	int to,w,nxt;
};
Edge e[N*2];
int n,cnt;
int head[N];
int maxn[N];
int smaxn[N];
int maxid[N];
int smaxid[N];

void init()
{
	cnt=0;
	memset(head,-1,sizeof(head));
}

void add(int u,int v,int w)
{
	e[cnt].to=v;
	e[cnt].w=w;
	e[cnt].nxt=head[u];
	head[u]=cnt++;
}

void read()
{
	int a,b;
	for(int i=2;i<=n;++i){
		scanf("%d%d",&a,&b);
		add(i,a,b);
		add(a,i,b);
	}
}

void dfs1(int u,int fa)
{
	maxn[u]=smaxn[u]=0;
	for(int i=head[u];i!=-1;i=e[i].nxt){
		int v=e[i].to;
		if(v==fa) continue;
		dfs1(v,u);
		if(e[i].w+maxn[v]>smaxn[u]){
			smaxn[u]=e[i].w+maxn[v];
			smaxid[u]=v;
			if(smaxn[u]>maxn[u]){
				swap(smaxn[u],maxn[u]);
				swap(smaxid[u],maxid[u]);
			}
		}
	}
}

void dfs2(int u,int fa)
{
	for(int i=head[u];i!=-1;i=e[i].nxt){
		int v=e[i].to;
		if(v==fa)continue;
		if(v==maxid[u]){
			if(e[i].w+smaxn[u]>smaxn[v]){
				smaxn[v]=e[i].w+smaxn[u];
				smaxid[v]=u;
				if(smaxn[v]>maxn[v]){
					swap(smaxn[v],maxn[v]);
					swap(smaxid[v],maxid[v]);
				}
			}
		}else{
			if(e[i].w+maxn[u]>smaxn[v]){
				smaxn[v]=e[i].w+maxn[u];
				smaxid[v]=u;
				if(smaxn[v]>maxn[v]){
					swap(smaxn[v],maxn[v]);
					swap(smaxid[v],maxid[v]);
				}
			}
		}
		dfs2(v,u);
	}
}

void solve()
{
	dfs1(1,-1);
	dfs2(1,-1);
	for(int i=1;i<=n;++i)
		printf("%d
",maxn[i]);
}

int main()
{
	while(~scanf("%d",&n))
	{
		init();
		read();
		solve();
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/20143605--pcx/p/5342435.html