两次搜索的方法
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; int N,V[10100]; vector<int>son[10100]; //图 int MAX[10100],MAXN[10100]; //最大值及其标号 int SMAX[10100],SMAXN[10100]; //次大值及其标号 bool vis[10100]; //标记访问状态 void dfs1(int n) //在以n为根节点的子树上求出节点n到叶子节点距离的最大值 { MAX[n]=SMAX[n]=0; int len=son[n].size(); for(int i=0;i<len;i++) { int k=son[n][i]; //儿子标号 - - dfs1(k); if(SMAX[n]<MAX[k]+V[k]) { SMAX[n]=MAX[k]+V[k]; SMAXN[n]=k; if(SMAX[n]>MAX[n]){ swap(SMAX[n],MAX[n]); swap(SMAXN[n],MAXN[n]); } } } } void dfs2(int n) //求出n的儿子们在树中能延伸的最大距离(n的最大距离及次大距离已得到) { int len=son[n].size(); vis[n]=1; for(int i=0;i<len;i++) { int k=son[n][i]; if(vis[k]) continue; if(k==MAXN[n]){ if(SMAX[k]<SMAX[n]+V[k]){ SMAX[k]=SMAX[n]+V[k]; SMAXN[k]=n; if(SMAX[k]>MAX[k]){ swap(SMAX[k],MAX[k]); swap(SMAXN[k],MAXN[k]); } } } else{ if(SMAX[k]<MAX[n]+V[k]){ SMAX[k]=MAX[n]+V[k]; SMAXN[k]=n; if(SMAX[k]>MAX[k]){ swap(SMAX[k],MAX[k]); swap(SMAXN[k],MAXN[k]); } } } dfs2(k); } } int main() { int i,j,k,u,v; while(scanf("%d",&N)!=EOF) { for(i=1;i<=N;i++) son[i].clear(); for(i=2;i<=N;i++){ scanf("%d%d",&u,&V[i]); son[u].push_back(i); //i的父亲是u } memset(vis,0,sizeof(vis)); dfs1(1); // 测试 // for(i=1;i<=N;i++) printf("~%d ",MAX[i]);printf("\n"); // for(i=1;i<=N;i++) printf("~%d ",SMAX[i]);printf("\n"); memset(vis,0,sizeof(vis)); dfs2(1); for(i=1;i<=N;i++) printf("%d\n",MAX[i]); } return 0; } /* 5 1 1 2 1 3 1 1 1 */