Computer
(树形DP入门)题意:给你一棵树,求树上每个点能达到的最远距离。
思路:
想求每个点能达到的最远距离,就有可能是到它的子节点的最远距离,或者通过它的父节点所能到达的最远距离。
这里的边是有向边。
用一个二维数组dp【mx】【3】,dp【u】【0】 表示u节点以下能达到的最远距离,dp【u】【1】表示u节点以下能达到的次远距离,dp【u】【2】表示通过它的父节点能走的最远距离。
求u子树下能达到的最远距离,显然是从树下到上。而求他父节点能达到的最远距离,则是从上往下,这就需要两个dfs,一个求dp【u】【0】和dp【u】【1】(下到上),另一个则是求dp【u】【2】(上到下)。
所以,dp[f][0]=dp[z][0]+a[i].w, dp[z][2]=max(dp[f][2],dp[f][1])+a[i].w;(dp[z][0]+a[i].w==dp[f][0]))dp[z][2]=max(dp[f][2],dp[f][0])+a[i].w;(dp[z][0]+a[i].w!=dp[f][0]))
最后答案就是max(dp[i][2],dp[i][0]);
AC代码:
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int mx=100010;
struct node{
int w,v,nex;
}a[mx<<1];
int dp[mx][3],h[mx],n,t;
int f[mx];
void add(int w,int v,int f)
{
a[t].w=w;
a[t].v=v;
a[t].nex=h[f];
h[f]=t++;
}
void dfs1(int f);
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(h,-1,sizeof(h));
memset(f,-1,sizeof(f));
memset(dp,0,sizeof(dp));t=0;
for(int i=1;i<=n;i++)
{scanf("%d",&dp[i][1]);}
int x,y;
while (scanf("%d%d",&x,&y)&&!(x==0&&y==0))
{ add(x,x,y);f[x]=y;}
int i=1;
while(f[i]!=-1) i=f[i];
dfs1(i);
printf("%d\n",max(dp[i][1],dp[i][0]));
}
return 0;
}
void dfs1(int f)
{
for(int i=h[f];i!=-1;i=a[i].nex)
{
int z=a[i].v;
dfs1(z);
{
dp[f][1]+=dp[z][0];
dp[f][0]+=max(dp[z][0],dp[z][1]);
}
}
}