题目大意:在一棵带边权的有根树中,对于每个点,找出它与离它最远的那个点的之间的距离。
题目分析:对于一个点,离它最远的点只有两种情况,一是它到叶子节点的最远距离,一是与它父亲的距离加上他的父亲到叶子节点的最远距离。因为它的父亲到叶子的最远距离的那条路径可能恰好经过它自己,所以还要求出每个点到叶子节点的次大距离。
代码如下:
# include<iostream> # include<cstdio> # include<vector> # include<cstring> # include<algorithm> using namespace std; const int N=10010; struct Edge { int to,w,nxt; }; Edge e[N*2]; int n,cnt; int head[N]; int maxn[N]; int smaxn[N]; int maxid[N]; int smaxid[N]; void init() { cnt=0; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { e[cnt].to=v; e[cnt].w=w; e[cnt].nxt=head[u]; head[u]=cnt++; } void read() { int a,b; for(int i=2;i<=n;++i){ scanf("%d%d",&a,&b); add(i,a,b); add(a,i,b); } } void dfs1(int u,int fa) { maxn[u]=smaxn[u]=0; for(int i=head[u];i!=-1;i=e[i].nxt){ int v=e[i].to; if(v==fa) continue; dfs1(v,u); if(e[i].w+maxn[v]>smaxn[u]){ smaxn[u]=e[i].w+maxn[v]; smaxid[u]=v; if(smaxn[u]>maxn[u]){ swap(smaxn[u],maxn[u]); swap(smaxid[u],maxid[u]); } } } } void dfs2(int u,int fa) { for(int i=head[u];i!=-1;i=e[i].nxt){ int v=e[i].to; if(v==fa)continue; if(v==maxid[u]){ if(e[i].w+smaxn[u]>smaxn[v]){ smaxn[v]=e[i].w+smaxn[u]; smaxid[v]=u; if(smaxn[v]>maxn[v]){ swap(smaxn[v],maxn[v]); swap(smaxid[v],maxid[v]); } } }else{ if(e[i].w+maxn[u]>smaxn[v]){ smaxn[v]=e[i].w+maxn[u]; smaxid[v]=u; if(smaxn[v]>maxn[v]){ swap(smaxn[v],maxn[v]); swap(smaxid[v],maxid[v]); } } } dfs2(v,u); } } void solve() { dfs1(1,-1); dfs2(1,-1); for(int i=1;i<=n;++i) printf("%d ",maxn[i]); } int main() { while(~scanf("%d",&n)) { init(); read(); solve(); } return 0; }