题意:
给出电脑网络连接树,求每个节点的为起点的最长距离
分析:
这道题开始状态想不出来,放了一段时间,后来注意到例题上有这道题,每个节点的最长距离可由父节点的最长距离,次长距离,和子节点的最长距离(三者取最大)决定。先用一个dfs求出各节点由各子树确定的最长距离,次长距离,再用一个dfs由父节点推各子节点的最长距离。
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<11 #define All 1,N,1 #define read freopen("in.txt", "r", stdin) #define N 10010 const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF= 0x7ffffff; const int mod = 1000000007; struct edge{ int t,d; }; //p[i]由父节点来的最长距离 //dp[i]由子树来的最长距离 //g[i]由子树来的次长距离 int dp[N],p[N],g[N],n,longest[N]; vector<edge>e[N]; int dfs(int root){ if(e[root].size()==0) return 0; if(dp[root])return dp[root];//记忆化搜索 int tmp; for(int i=0;i<e[root].size();++i){ int son=e[root][i].t; int cost=e[root][i].d; if(dfs(son)+cost>dp[root]){ g[root]=dp[root]; dp[root]=dp[son]+cost; tmp=son; } else if(dp[son]+cost>g[root])g[root]=dp[son]+cost; } longest[root]=tmp;//把取最长距离的子节点存起来,方便后面由次长距离的更新最长 return dp[root]; } void dfs1(int root){ for(int i=0;i<e[root].size();++i){ int son=e[root][i].t; int cost=e[root][i].d; if(son==longest[root])//若在该子节点取得最长距离 ,由父节点的来自父节点的最长距离和来自子树的次长距离更新 p[son]=max(p[root],g[root])+cost; else p[son]=max(p[root],dp[root])+cost;//否则,由父节点的来自父节点的最长距离和来自子树的最长距离更新 dfs1(son); } } int main() { while(~scanf("%d",&n)){ edge b; int a; memset(dp,0,sizeof(dp)); memset(p,0,sizeof(p)); memset(g,0,sizeof(g)); for(int i=1;i<=n;++i){ e[i].clear(); } for(int i=2;i<=n;++i){ scanf("%d%d",&a,&b.d); b.t=i; e[a].push_back(b); } dfs(1); dfs1(1); for(int i=1;i<=n;++i){ printf("%d\n",max(p[i],dp[i])); } } return 0; }
时间: 2024-10-21 04:13:16