题意:求每个点的最远距离
思路:对于有向图<u,v> dp[u][0] 表示 u向子节点(向下)能到达的最圆距离
dp[u][1] 表示 u向子节点能到达的此远距离
dp[u][2] 表示 u向父节点(向上)能到达的最远距离
第一次 dfs 从下到上遍历图求出 dp[u][0] dp[u][1],
第二次 dfs 从上到下遍历图求出 dp[u][2];
代码还有解释
#include<stdio.h>
#include<string.h>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=5e4+10;
struct node
{
int v,ne,w;
}edge[N];
int head[N],isroot[N];
int dp[N][3];
int e,n;
void add(int a,int b,int c)
{
edge[e].v=b;
edge[e].w=c;
edge[e].ne=head[a];
head[a]=e++;
}
void dfs1(int u)
{
for(int i=head[u];i!=-1;i=edge[i].ne)
{
int v=edge[i].v;
dfs1(v);
int temp=dp[v][0]+edge[i].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].ne)
{
int v=edge[i].v;
int w=edge[i].w;
if(dp[u][0]==dp[v][0]+w)
dp[v][2]=max(dp[u][2],dp[u][1])+w;
//如果此时v就是u向下走的最长距离树枝的节点,
//那么让dp[u][2],dp[u][1]比较,因为要更新向上走的最远距离;
//向上走的最远距离可能是u向上走的最远距离也可能是从u到子节点的此远距离(因为此时为u向下的最远距离的树枝)
else
dp[v][2]=max(dp[u][2],dp[u][0])+w;
//否则用dp[u][2],dp[u][0]比较,更新v向上走的最远距离
dfs2(v);
}
}
int main()
{
while(~scanf("%d",&n))
{
int a,b,c;
memset(head,-1,sizeof(head));
memset(isroot,0,sizeof(isroot));
e=0;
for(int i=2;i<=n;i++)
{
scanf("%d %d",&b,&c);
add(b,i,c);
}
memset(dp,0,sizeof(dp));
dfs1(1);
dfs2(1);
for(int i=1;i<=n;i++)
printf("%d\n",max(dp[i][2],dp[i][0]));
//最后让向上的最远距离和向下的最远距离比较
}
return 0;
}