HDU 2196 Computer
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2196
题目大意:给你一颗树,求树上一节点到其他节点的最远距离。
输入:一个整数N代表有N个节点,然后N-1(从第二行到第N行)行,每行两个数字a,b代表第a台电脑和第i台电脑连接的长度。
输出:每个节点到其他节点的最远距离
此题需要两次dfs,一次算出他到子节点的最大距离,另一次算出他父亲走过的最远距离加上他和父亲之间的距离。而每个节点到子节点的距离需要存储第一大和第二大。因为如果只存最大值的话,判断一个点的从父节点过来的最大值,
那么如果他的父节点存的最大值正好是从该点过来的,那么就失去了从父节点过来的状态,所以要记录最大的两个值。
对于一个节点i dp[i][0]表示从子节点的最大值,显示这是一种可能的答案
dp[i][2]表示从父亲节点过来的最大值
- dp[2][v] = max( dp[0][u]+weight(u,v) , dp[2][u]+weight(u,v) ) (v是u的儿子 且 u往下走的最远距离不经过v)
- dp[2][v] = max( dp[1][u]+weight(u,v) , dp[2][u]+weight(u,v) ) (v是u的儿子 且 u往下走的最远距离经过v)
代码如下:
#include<bits/stdc++.h> using namespace std; #define maxn 10000+50 int dp[maxn][3]; struct node { int to; int val; int next; }edge[maxn*2]; int head[maxn],tot,n; void init() { for(int i=1;i<=n;i++) { head[i]=-1; } tot=0; memset(edge,0,sizeof(edge)); } void add(int u,int v,int w) { edge[tot].to=v; edge[tot].val=w; edge[tot].next=head[u]; head[u]=tot++; } void dfs1(int u) { for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; dfs1(v); int w=edge[i].val; int temp=dp[v][0]+w; if(temp>=dp[u][0]) { dp[u][1]=dp[u][0]; dp[u][0]=temp; } else if(temp>dp[u][1]) dp[u][1]=temp; } } void dfs2(int u) { for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(dp[u][0]==dp[v][0]+edge[i].val) { dp[v][2]=max(dp[u][2],dp[u][1])+edge[i].val; } else { dp[v][2]=max(dp[u][2],dp[u][0])+edge[i].val; } dfs2(v); } } int main() { while(scanf("%d",&n)!=EOF) { init(); for(int i=2;i<=n;i++) { int a,b; cin>>a>>b; add(a,i,b); } memset(dp,0,sizeof(dp)); dfs1(1); dfs2(1); for(int i=1;i<=n;i++) printf("%d ",max(dp[i][0],dp[i][2])); } return 0; }