题意
N台计算机,N-1条线相连,问这N台计算机每一台计算机到另一台计算机的最长距离是多少。
题解
一道很好的树形DP题目。首先的话,对于一个点要搞清楚寻找最长距离所能转移的三个状态。一种状态是沿着子节点DFS,寻找最长距离。第二种状态是,先向父节点走一步,然后沿着另一条线路DFS。第三种状态是,向父节点走多步。
针对这三种状态,可以使用一个二维DP数组对状态进行记录。使用dp[0][x]代表向下走的最长距离,用dp[1][x]代表向下走的次长距离,dp[2][x]代表向上走的最长距离。首先一遍DFS就可以求得dp[0][x],dp[1][x]。然后再来一遍DFS,求得dp[2][x]。dp[2][x]的计算也算是个小技巧吧,在父状态对子状态的dp[2][x]进行赋值,这样的话就可以保证子状态转移到父状态之后不会再转移回去。
注意事项
这道题最重要的是想法,没有什么坑。注意一下初始化就行了。
代码
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<string>
#include<set>
#include<map>
#include<bitset>
#include<stack>
#define UP(i,l,h) for(int i=l;i<h;i++)
#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)
#define W(a) while(a)
#define MEM(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f3f3f3f3f
#define LL long long
#define MAXN 10010
#define SIZE 95
#define EPS 1e-10
#define MOD 1000000007
using namespace std;
struct Node {
int son,val;
Node(int son,int val):son(son),val(val) {}
};
vector<Node> nodes[MAXN];
int p[MAXN],mxson[MAXN];
int dp[3][MAXN];
int dfs(int u) {
if(dp[0][u]>0)
return dp[0][u];
int sz=nodes[u].size();
UP(i,0,sz) {
Node son=nodes[u][i];
int d=dfs(son.son)+son.val;
if(d>dp[0][u]) {
dp[0][u]=d;
mxson[u]=son.son;
}
}
UP(i,0,sz) {
Node son=nodes[u][i];
// cout<<" xx"<<son.son<<" "<<u<<" "<<mxson[u]<<endl;
if(son.son==mxson[u]) {
continue;
}
int d=dp[0][son.son]+son.val;
// cout<<d<<endl;
if(d>dp[1][u]) {
dp[1][u]=d;
}
}
return dp[0][u];
}
void dfs2(int u) {
int sz=nodes[u].size();
UP(i,0,sz) {
Node son=nodes[u][i];
// cout<<"son"<<son.son<<" "<<dp[2][u]<<" "<<dp[1][u]<<endl;
if(son.son==mxson[u]) {
dp[2][son.son]=max(dp[2][u],dp[1][u])+son.val;
} else {
dp[2][son.son]=max(dp[2][u],dp[0][u])+son.val;
}
dfs2(son.son);
}
}
int main() {
int n;
W(~scanf("%d",&n)) {
MEM(dp,0);
MEM(mxson,0);
UP(i,1,n+1){
nodes[i].clear();
}
int pa,val;
UP(i,2,n+1) {
scanf("%d%d",&pa,&val);
p[i]=pa;
nodes[pa].push_back(Node(i,val));
}
dfs(1);
dfs2(1);
UP(i,1,n+1)
printf("%d\n",max(dp[0][i],dp[2][i]));
}
}