Description
给出一棵无向树,求树的直径,即树上两点之间的最长距离
Input
每行三个整数a,b,c表示树上a点与b点之间有权值为c的一条边,以文件尾结束输入
Output
输出树的直径
Sample Input
5 1 6
1 4 5
6 3 9
2 6 8
6 1 7
Sample Output
22
Solution
先给出一个结论:
从任一点s出发,距此点距离最远的点为直径的一个端点a,那么距a最远的点b即为直径的另一个端点,a与b之间的距离即为直径长度
此题为求树的直径裸题,分两部分,首先从任一点出发开始dfs,不妨从1开始,用树形dp求出任一点距1点的距离,找到距其最远点s,然后以s为起点再dfs一遍,求出所有点距s的距离,其中的最大值即为树的直径
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 11111
struct node
{
int to,c,next;
}edge[2*maxn];
int n,head[maxn],tot,dis[maxn],vis[maxn];
void add(int u,int v,int c)
{
edge[tot].to=v;
edge[tot].c=c;
edge[tot].next=head[u];
head[u]=tot++;
}
void dfs(int u)
{
for(int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].to,c=edge[i].c;
if(!vis[v])
{
vis[v]=1;
dis[v]=dis[u]+c;
dfs(v);
}
}
}
int main()
{
memset(head,-1,sizeof(head));
tot=n=0;
int u,v,c,s;
while(~scanf("%d%d%d",&u,&v,&c))
{
n=max(n,u),n=max(n,v);
add(u,v,c),add(v,u,c);
}
if(!n)printf("0\n");
else
{
memset(vis,0,sizeof(vis));
dis[1]=0,vis[1]=1;
dfs(1);
for(int i=2,temp=-1;i<=n;i++)
if(dis[i]>temp)temp=dis[i],s=i;
memset(vis,0,sizeof(vis));
dis[s]=0,vis[s]=1;
dfs(s);
int ans=-1;
for(int i=1;i<=n;i++)
ans=max(ans,dis[i]);
printf("%d\n",ans);
}
return 0;
}