Computer(hdu 2196)
题意:给出一棵树,求出每个点与距离它最远的点的距离。
/* 树形DP 先把无根树转为有根树,对于一个节点i来说,与它相距最远的点有两种可能,一是在它的子树中,二是不在,我们分别用f[i][0]和f[i][1]来表示。 f[i][0]很好求,从子节点向它的父亲递推就可以了。 关键在于求f[i][1],我们发现f[i][1]可能有两种情况,一是来自它父亲的子树,而是来自它父亲的f[j][1],然后判断一下就好了。 */ #include<iostream> #include<cstdio> #include<cstring> #define N 10010 #define lon long long using namespace std; int head[N],vis[N],n,cnt; lon f[N][2]; struct node{int v,w,pre;}e[N*2]; void add(int u,int v,int w){ e[++cnt].v=v;e[cnt].w=w;e[cnt].pre=head[u];head[u]=cnt; e[++cnt].v=u;e[cnt].w=w;e[cnt].pre=head[v];head[v]=cnt; } lon dfs1(int u){ vis[u]=1; for(int i=head[u];i;i=e[i].pre){ if(vis[e[i].v]) continue; f[u][0]=max(f[u][0],dfs1(e[i].v)+e[i].w); } return f[u][0]; } void dfs2(int u){ vis[u]=1; lon max1=0,max2=0;int v1,v2; for(int i=head[u];i;i=e[i].pre){ int v=e[i].v,w=e[i].w; if(vis[v]) continue; if(f[v][0]+w>max1){ max2=max1;v2=v1; max1=f[v][0]+w;v1=v; } else if(f[v][0]+w>max2){ max2=f[v][0]+w;v2=v; } } if(u!=1){ if(f[u][1]>max1){ max2=max1;v2=v1; max1=f[u][1];v1=-1; } else if(f[u][1]>max2){ max2=f[u][1];v2=-1; } } for(int i=head[u];i;i=e[i].pre){ int v=e[i].v; if(vis[v]) continue; if(v1!=v) f[v][1]=max1+e[i].w; else f[v][1]=max2+e[i].w; dfs2(e[i].v); } } void work(){ for(int u=2;u<=n;u++){ int v,w;scanf("%d%d",&v,&w); add(u,v,w); } memset(vis,0,sizeof(vis)); dfs1(1); memset(vis,0,sizeof(vis)); dfs2(1); for(int i=1;i<=n;i++) cout<<max(f[i][0],f[i][1])<<endl; } int main(){ freopen("jh.in","r",stdin); while(scanf("%d",&n)!=EOF){ memset(head,0,sizeof(head)); memset(f,0,sizeof(f)); cnt=0; work(); } return 0; }