您的位置:首页 > 其它

hdu2196:Computer (树形dp)

2018-04-01 21:54 501 查看

题意

hdu2196

求树上每个点能到达的最远距离

题解

呜呜呜网上说是..基础题【捂脸】

下面说正题…

每个点能到达的最远距离无非两种,一种向下一直走到底,一种向上走一段在下到底

因此对于每一个点记录dp[i][0]dp[i][0]表示子树中最远距离;dp[i][1]dp[i][1]表示子树中次远距离;dp[i][2]dp[i][2]表示通过父节点向上的那条最远路径

至于转移,用一次dfs可以求出dp[i][0]、dp[i][1]dp[i][0]、dp[i][1]

再用一次dfs求出dp[i][2]dp[i][2]

dp[i][2]={max(dp[fa[i]][2],dp[fa[i]][1])+w(fa[i],i)max(dp[fa[i]][2],dp[fa[i]][0])+w(fa[i],i)i在fa[i]子树最远路径上i不在fa[i]子树最远路径上dp[i][2]={max(dp[fa[i]][2],dp[fa[i]][1])+w(fa[i],i)i在fa[i]子树最远路径上max(dp[fa[i]][2],dp[fa[i]][0])+w(fa[i],i)i不在fa[i]子树最远路径上

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 11000
int n,num=0,dp
[3],d
,h
,mx
;
struct node{int x,y,z,next;}mp[2*N];
//dp[i][0]表示子树最远距离
//dp[i][1]表示子树次远距离
//dp[i][2]表示从父节点来的最远距离
void insert(int x,int y,int z){
mp[++num].x=x;mp[num].y=y;mp[num].z=z;mp[num].next=h[x];h[x]=num;
mp[++num].x=y;mp[num].y=x;mp[num].z=z;mp[num].next=h[y];h[y]=num;
}
void dfs1(int u){
dp[u][0]=0;dp[u][1]=0;
for(int i=h[u];i;i=mp[i].next){
int v=mp[i].y;
if(!d[v]){
d[v]=d[u]+1;dfs1(v);
if(dp[v][0]+mp[i].z>=dp[u][0]) dp[u][1]=dp[u][0],dp[u][0]=dp[v][0]+mp[i].z,mx[u]=v;
else if(dp[v][0]+mp[i].z>dp[u][1]) dp[u][1]=dp[v][0]+mp[i].z;
else if(dp[v][1]+mp[i].z>dp[u][1]) dp[u][1]=dp[v][1]+mp[i].z;
}
}
}
void dfs2(int u){
for(int i=h[u];i;i=mp[i].next){
int v=mp[i].y;
if(d[v]==d[u]+1){
if(mx[u]==v) dp[v][2]=max(dp[u][1],dp[u][2])+mp[i].z;
else dp[v][2]=max(dp[u][2],dp[u][0])+mp[i].z;
dfs2(v);
}
}
}
int main(){
while(scanf("%d",&n)>0){
memset(h,0,sizeof(h)); num=0;
memset(d,0,sizeof(d));
memset(dp,0,sizeof(dp));
memset(mx,0,sizeof(mx));
for(int i=2;i<=n;i++){
int x,y;scanf("%d%d",&x,&y);
insert(i,x,y);
}d[1]=1;dfs1(1);dfs2(1);
for(int i=1;i<=n;i++) printf("%d\n",max(dp[i][0],dp[i][2]));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: