HDU2196- Computer (树形DP/ 树上点可到的最远距离)

Computer

题目大意:
就是求树上每个点可到的最远距离,(不是树的直径)是单向可走的最远距离。

解题思路:
虽然不是树的直径但是也和树的直径有着一定的关系,在树形dp求树的直径中,f数组求的是该节点到子树的最远距离,这里我们也用到了这个东西。不过我们又新建了两个数组。
dp[i][0] 表示以 i 为根的子树上的节点到 i 的最长距离。 //之前的f数组
dp[i][1] 表示以 i 为根的子树上的节点到 i 的次长距离。
dp[i][2] 表示从 i 向父亲节点能走的最长距离。 //第二次dfs解得

图画的好像有点乱
在这里插入图片描述

然后比较子树向下和父节点向上的路即可

Code:

#include <iostream>
#include <cstdio>
#include<cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#define inf 9654234
#define ll unsigned long long
using namespace std;
const int maxn=1e4+7;
const ll mod=4294967296;


int f[maxn],dp[maxn][3],mx[maxn],ans=0;
vector<pair<int,int>> ve[maxn];

void dfs(int u,int fa){
	for(auto it:ve[u]){
		int v=it.first;
		int w=it.second;
		if(v==fa) continue;
		dfs(v,u);
		if(dp[v][0]+w>dp[u][0]){
			mx[u]=v;
			dp[u][1]=dp[u][0];
			dp[u][0]=dp[v][0]+w;
		}
		else if(dp[v][0]+w>dp[u][1]){
			dp[u][1]=dp[v][0]+w;
		}
	}
}

void dfs2(int u,int fa){
	for(auto it:ve[u]){
		int v=it.first;
		int w=it.second;
		if(v==fa) continue;
		if(v==mx[u]) dp[v][2]=w+max(dp[u][2],dp[u][1]);
		else dp[v][2]=w+max(dp[u][2],dp[u][0]);
		dfs2(v,u);
	}
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
    int n;
    while(cin>>n){
    	for(int i=1;i<=n;i++) {
    		ve[i].clear();
    		dp[i][0]=dp[i][1]=dp[i][2]=0;
		}
    	for(int i=2;i<=n;i++){
    		int u,v,w;
    		cin>>v>>w;
    		ve[i].push_back(make_pair(v,w));
    		ve[v].push_back(make_pair(i,w));
		}
		dfs(1,0);
		dfs2(1,0);
		for(int i=1;i<=n;i++) cout<<max(dp[i][0],dp[i][2])<<"\n";
	}

	
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43872264/article/details/107921662