Computer


链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2196
https://blog.youkuaiyun.com/shuangde800/article/details/9732825


#include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<queue> #include<cmath> #include<cstring> using namespace std; typedef long long int64; const int INF = 0x3f3f3f3f; const double PI = acos(-1.0); const int MAXN = 10010; struct Node { int v, w; }; vector<Node>adj[MAXN]; int indeg[MAXN]; int val[MAXN]; int n, m; int64 f[MAXN][2]; int vis[MAXN]; int64 dfs1(int u) //从自己开始 { vis[u]=true; //标记自己 f[u][0] = 0; //自己到原点的距离初始化0; for(int i=0;i<adj[u].size();++i)//自己到每个点的距离取最大值 { int v = adj[u][i].v; //节点 int w = adj[u][i].w; //到节点的权值 if(vis[v]) //被标记跳过 continue; f[u][0]=max(f[u][0],dfs1(v)+w); //自己到原点的最大距离=自己到原点的距离节点到自己的距离加上自己到谁大 } return f[u][0];//返回节点到自己的距离 } void dfs2(int u, int fa_w) { vis[u] = true;//标记自己 int max1=0, v1, max2=0, v2; //初始化 for(int i=0; i<adj[u].size(); ++i) { int v=adj[u][i].v; //节点 int w=adj[u][i].w; //到节点的权值 if(vis[v]) continue; //被标记跳过 int tmp=f[v][0]+w; //距离为目标节点到叶子加上自己到节点的权值。 if(tmp>max1) //(第一次t)如果下一个子节点距离更长 { max2=max1; //(第一次为0)赋上次值 v2=v1; //(第一次。。) 为次节点 max1=tmp; //(第一次为目标节点到叶子加上自己到节点的权值。) v1=v; //(第一次为目标权值) } else if(tmp==max1||tmp>max2) //如果与次值相等或者比次值大 { max2=tmp;//次值等于这个值 。 v2=v;//次值节点为次节点。 } } if(u!= 1) //如果不为根节点 { int tmp = f[u][1];//除去子节点最长距离的子节点最长距离 int v = -1;//目标节点为-1; if(tmp > max1) { max2=max1; v2=v1; max1=tmp; v1=v; } else if(tmp==max1||tmp>max2) { max2=tmp; v2=v; } } for(int i=0; i<adj[u].size(); ++i) { int v=adj[u][i].v; int w=adj[u][i].w; if(vis[v]) continue; if(v==v1) { f[v][1] = max2 + w; } else { f[v][1] = max1 + w; } dfs2(v, w); } } int main() { while(~scanf("%d", &n) && n) { for(int i=1;i<=n;++i) adj[i].clear(); for(int u=2;u<=n;++u) { int v,w; scanf("%d%d", &v, &w); adj[u].push_back((Node){v,w}); //装入目标节点,权值 adj[v].push_back((Node){u,w}); //装入自己,权值 } memset(f, 0, sizeof(f)); memset(vis, 0, sizeof(vis)); dfs1(1); memset(vis, 0, sizeof(vis)); dfs2(1, 0); for(int i=1; i<=n; ++i){ cout<<max(f[i][0],f[i][1])<<endl; } } return 0; }

 

转载于:https://www.cnblogs.com/JCRL/p/10072376.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值