Computer
Hint: the example input is corresponding to this graph. And from the graph, you can see that the computer 4 is farthest one from 1, so S1 = 3. Computer 4 and 5 are the farthest ones from 2, so S2 = 2. Computer 5 is the farthest one from 3, so S3 = 3. we also get S4 = 4, S5 = 4.
题意:有n台电脑,有(n-1)条边连接,每条边有权值,问每台电脑距离其他电脑的最远距离是多少。
题解:树形DP。要求一个点到其他点的最远距离的话,得出此点最大距离 = max ( max (此点子树方向的最大距离) , max (此点父亲方向的最大距离) ),此点子树方向的最大距离深搜即可求得,下面开始求此点父亲方向的最大距离。
令dp[i][0]表示为节点i子树方向的最大距离,dp[i][1]表示为节点i子树方向的次大距离,dp[i][2]表示为i节点父亲方向的最大距离,s表示为子节点,f表示为父节点,w表示为子父节点的距离。
那么存在两种情况:
① s在f子树方向的最大距离路径上。
dp[s][2]=max(dp[f][1],dp[f][2])+w;
② s不在f子树方向的最大距离路径上。
dp[s][2]=max(dp[f][0],dp[f][2])+w;
代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=10005;
struct node
{
int v,w;
node(){}
node(int a,int b)
{v=a;w=b;}
};
vector<node> e[maxn];
int n,dp[maxn][3];
void dfs1(int s,int fa);
void dfs2(int s,int fa);
int main()
{
int i,j,a,b;
while(~scanf("%d",&n))
{
for(i=0;i<maxn;i++) e[i].clear();
fill(dp[0],dp[0]+maxn*3,0);
for(i=2;i<=n;i++)
{
scanf("%d%d",&a,&b);
e[i].push_back(node(a,b));
e[a].push_back(node(i,b));
}
dfs1(1,-1);
dfs2(1,-1);
for(i=1;i<=n;i++) printf("%d\n",max(dp[i][0],dp[i][2]));
}
system("pause");
return 0;
}
void dfs1(int s,int fa) //子树方向的最大距离和次大距离
{
int i,v,w;
for(i=0;i<e[s].size();i++)
{
v=e[s][i].v;
if(v==fa) continue;
dfs1(v,s);
w=dp[v][0]+e[s][i].w;
if(w>=dp[s][0])
{
dp[s][1]=dp[s][0];
dp[s][0]=w;
}
else if(w>dp[s][1]) dp[s][1]=w;
}
}
void dfs2(int s,int fa) //父亲方向的最大距离
{
int i,v,w;
for(i=0;i<e[s].size();i++)
{
v=e[s][i].v;w=e[s][i].w;
if(v==fa) continue;
if(dp[s][0]==dp[v][0]+w) dp[v][2]=max(dp[s][1],dp[s][2])+w;
else dp[v][2]=max(dp[s][0],dp[s][2])+w;
dfs2(v,s);
}
}