题目描述 Description |
【问题描述】 味味最近对树很感兴趣,什么是树呢?树就是有 n个点和n-1条边形成的无环连通无向图。 今年2012年浙江省队选拔赛中味味发现了一个树中最长链(就是树当中距离最远的点对)试题, 于是她着手对树进行了一些研究和思考。 味味在研究过程中想知道,对于一个无根树,当节点i作为根的时候树的高是多少。所谓树高 指的是从根节点出发,到离根节点最远叶子节点所经过的节点的总数,详见输入输出样例 1。 味味现在遇到了一些烦心的事情,不想再继续思考了,请你帮助她解决这个问题。 【输入】 输入文件名为 tree.in,共 N 行。第一行为一个正整数 N,表示树的节点个数。第 2行到第 N 行里,每行两个用空格隔开的正整数a 和 b,表示a 与b有连边。 【输出】 输出文件 tree.out 共 N 行,第 i行表示以节点 i为根时的树高。 |
样例输入 Sample Input |
输入(一) 3 1 2 2 3 输入(二) 4 1 4 2 4 3 4 |
样例输出 Sample Output |
输出(一) 输出(二) |
时间限制:所有句子相加不超过1亿句。 1亿就是1秒 空间限制:所有数组相加不超过1000万。 约40M内存 |
【数据说明】 对于 30%的数据有 N≤ 100。 对于 60%的数据有 N≤ 300。 对于 100%的数据有 1≤N≤1000,1≤a,b≤N 时间限制为1秒 |
这题应该用父亲寻找法吧。
先一遍预处理出以1为根的固定的一棵树,然后对于每个点,它还可以从父亲-爷爷那条线过来,也可以从自己的兄弟处过来。
看代码和注释吧。
#include<bits/stdc++.h>
using namespace std;
int head[300000],//head[i]记录节点i的第一条编号
next[300000],//每条边编两个号,这个数组大小是边数量的两倍
son[300000],//son[i]表示第i号边走过去的儿子节点号
p[300000];//这个是节点的访问标记
int tot,ans,n,i,x,y;
void add(int x,int y)
{
tot++;//边编号
son[tot]=y;
next[tot]=head[x];
head[x]=tot;
}
void dfs(int x,int s)
{
ans=max(ans,s);
for(int i=head[x];i!=0;i=next[i])//枚举边
{
if(p[son[i]]) continue;//访问过的儿子过掉
p[son[i]]=1;
dfs(son[i],s+1);
p[son[i]]=0;
}
}
int main()
{
cin>>n;
for(i=1;i<=n;i++)
head[i]=0;//链表的结束符号
for(i=1;i<n;i++)
{
cin>>x>>y;
add(x,y);
add(y,x);
}
for(i=1;i<=n;i++)//枚举每个点当树根
{
ans=-INT_MAX;
memset(p,0,sizeof(p));
p[i]=1;
dfs(i,1);
p[i]=0;
cout<<ans<<endl;
}
}
谢谢观看!