题目:求出一棵树上的所有点到其他点的最长距离。
思路:取一个根节点进行dfs,先求出每个节点到子节点的最长路和次长路(也就是与最长路不同的最长的路,有可能与最长路长度相等),并记录最长路和次长路通过的相邻节点的标号。然后进行第二次dfs,考虑最长路是通过父节点的情况,如果该节点v在父节点的最长路上,那么需要取次长路,否则就取最长路。
第二次dfs的时候最长路的通过节点还是要更新,因为若某个父节点的最长路是朝祖先走的,那么其子节点的最长路一定朝祖先走,且与v是否在父节点向下的最长路上无关。
#include<iostream> #include<map> #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<vector> #include<queue> #include<stack> #include<functional> #include<set> #include<cmath> #define pb push_back #define fs first #define se second #define sq(x) (x)*(x) #define eps 0.0000000001 using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int maxv=1e4+300; int N; vector<P> G[maxv]; int maxd[maxv],maxdn[maxv],smaxd[maxv],smaxdn[maxv]; void dfs1(int u,int f){ maxd[u]=smaxd[u]=0; for(int i=0;i<G[u].size();i++){ int v=G[u][i].fs; int len=G[u][i].se; if(v==f) continue; dfs1(v,u); if(len+maxd[v]>smaxd[u]){ smaxd[u]=len+maxd[v]; smaxdn[u]=v; } if(smaxd[u]>maxd[u]){ swap(smaxd[u],maxd[u]); swap(smaxdn[u],maxdn[u]); } } } void dfs2(int u,int f){ for(int i=0;i<G[u].size();i++){ int v=G[u][i].fs; int len=G[u][i].se; if(v==f) continue; if(maxdn[u]==v){ if(smaxd[u]+len>smaxd[v]){ smaxd[v]=smaxd[u]+len; smaxdn[v]=u; } if(smaxd[v]>maxd[v]){ swap(maxd[v],smaxd[v]); swap(maxdn[v],smaxdn[v]); } }else{ if(maxd[u]+len>smaxd[v]){ smaxd[v]=maxd[u]+len; smaxdn[v]=u; } if(smaxd[v]>maxd[v]){ swap(maxd[v],smaxd[v]); swap(maxdn[v],smaxdn[v]); } } dfs2(v,u); } } int main(){ /////freopen("/home/files/CppFiles/in","r",stdin); /* std::ios::sync_with_stdio(false); std::cin.tie(0);*/ while(cin>>N){ for(int i=1;i<=N;i++) G[i].clear(); for(int i=2;i<=N;i++){ int a,b; scanf("%d%d",&a,&b); G[i].pb(P(a,b)); G[a].pb(P(i,b)); } dfs1(1,-1); dfs2(1,-1); for(int i=1;i<=N;i++){ printf("%d\n",maxd[i]); } } return 0; }
时间: 2024-10-02 05:57:25