hdu2196
分析
经典的树型dp,值得回味,最大距离的点,要么是自己子树的内的点,要么是由父节点得到的最大距离+这个点到父节点的距离。考虑子树的点,bfs即可。对于父节点,其一是父节点的父节点得出最大值,其二就是父节点子树得出的最大值,如果父节点子树最大距离的点是在目标点的子树中,那么就会“进去”再“出来”,不符合最长,所以要再记一下第二大的值。dp[i][0]表示i点子树得出第一大的距离,dp[i][1]表示i点子树得出第二大的距离,dp[i][2]表示i点由父节点得到的最大距离。
题目
http://acm.hdu.edu.cn/showproblem.php?pid=2196
代码
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <vector>
#define ll __int64
using namespace std;
const int maxn=10010;
struct node
{
int w,v;
node(int vv,int ww)
{
v=vv;
w=ww;
}
};
vector<node> data[maxn];
int n;
int dp[maxn][3];
int vis[maxn];
void dfs1(int u)
{
int biggest=0,bigger=0;
vis[u]=1;
for(int i=0; i<data[u].size(); i++)
{
int vv=data[u][i].v;
int ww=data[u][i].w;
if(!vis[vv])
{
dfs1(vv);
int temp=dp[vv][0]+ww;
if(temp>biggest)
{
bigger=biggest;
biggest=temp;
}
else if(temp>bigger)
{
bigger=temp;
}
}
}
dp[u][0]=biggest;
dp[u][1]=bigger;
}
void dfs2(int u)
{
vis[u]=1;
for(int i=0; i<data[u].size(); i++)
{
int vv=data[u][i].v;
int ww=data[u][i].w;
if(!vis[vv])
{
if((dp[u][0]-ww)==dp[vv][0])
{
dp[vv][2]=max(dp[vv][2],max(dp[u][1],dp[u][2])+ww);
}
else
{
dp[vv][2]=max(dp[vv][2],max(dp[u][0],dp[u][2])+ww);
}
dfs2(vv);
}
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1; i<=n; i++)
data[i].clear();
for(int i=2; i<n+1; i++)
{
int v,w;
scanf("%d %d",&v,&w);
data[i].push_back(node(v,w));
data[v].push_back(node(i,w));
}
memset(vis,0,sizeof(vis));
dfs1(1);
memset(vis,0,sizeof(vis));
for(int i=1; i<=n; i++)
dp[i][2]=0;
dfs2(1);
for(int i=1; i<=n; i++)
printf("%d\n",max(dp[i][0],dp[i][2]));
}
return 0;
}