这道题和之前做的“UVALive-6056/Gym-101472I Tree”几乎一模一样。
(博客链接:https://blog.csdn.net/Cc_Sonia/article/details/82155123)
当时不太明白为什么三遍dfs就行了,这次看了大佬博客Orz:
https://blog.csdn.net/silent0001/article/details/52144104
豁然开朗啊Orz。我写好了一直WA,最后发现是因为数组开小了。。。。。
理解都在代码里了,附上AC代码:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAX=10005;
int n;
struct Edge
{
int to,next;
int w;
}edge[MAX*2];//注意开两倍!
int head[MAX],tot;
void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)
{
edge[tot].to=v;edge[tot].w=w;
edge[tot].next=head[u];head[u]=tot++;
}
bool vis[MAX];
int dis1[MAX],dis2[MAX];
void dfs1(int u)
{
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(!vis[v])
{
vis[v]=true;
dis1[v]=dis1[u]+edge[i].w;
dfs1(v);
}
}
}
void dfs2(int u)
{
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(!vis[v])
{
vis[v]=true;
dis2[v]=dis2[u]+edge[i].w;
dfs2(v);
}
}
}
int main()
{
while(scanf("%d",&n)==1)
{
if(n==1)
{
printf("0\n");
continue;
}
init();//注意!
int u,v,w;
for(int i=2;i<=n;i++)
{
v=i;
scanf("%d%d",&u,&w);
addedge(u,v,w);
addedge(v,u,w);
}
int st=1;
memset(vis,false,sizeof(vis));
memset(dis1,0,sizeof(dis1));
vis[st]=true;
dfs1(st);
int pos=-1,ma=-1;
for(int i=1;i<=n;i++)//找到直径的一个端点A
if(dis1[i]>ma)
{
pos=i;
ma=dis1[i];
}
//cout<<"pos1="<<pos<<endl;
memset(vis,false,sizeof(vis));
memset(dis1,0,sizeof(dis1));
st=pos;//一个端点A
vis[st]=true;
dfs1(st);
pos=-1,ma=-1;
for(int i=1;i<=n;i++)//找到直径的另一个端点B
if(dis1[i]>ma)
{
pos=i;
ma=dis1[i];
}
/*for(int i=1;i<=n;i++) //A到其余各点的距离
cout<<dis1[i]<<" ";
cout<<endl;
cout<<endl<<"pos2="<<pos<<endl;*/
memset(vis,false,sizeof(vis));
memset(dis2,0,sizeof(dis2));
st=pos;//另一个端点B
vis[st]=true;
dfs2(st);
/*for(int i=1;i<=n;i++) //B到其余各点的距离
cout<<dis2[i]<<" ";
cout<<endl;*/
for(int i=1;i<=n;i++)
printf("%d\n",max(dis1[i],dis2[i])); //两者的较大值即为结果
}
return 0;
}
之前那道UVA的题,用这个代码(改下scanf("%d%d%d",&u,&v,&w) 就行)交上去也过了,现在终于是对树的直径比较理解了。。