题解 P3884 【[JLOI2009]二叉树问题】
看了一下发现大家都是 LCA 做的。
我这里给大家提供一种使用 Floyd 算法的做法。
树其实一种特殊的图。
即没有环路,一定联通,而且有且有只有一个节点没有入度的图。
那么树上任意两点间的距离可以直接通过最短路算法获得。
树的深度就是距离根节点最远的那个点的距离。
树的宽度是节点最多的一层,同一层的节点距离根节点的距离都是相同的,所以也可以直接枚举获得。
Floyd 算法应该是相当基础的算法,我相信大佬们应该都会。
代码:
#include<bits/stdc++.h>
#define r read()//偷懒
#define lnf INT_MAX/4
// INT_MAX 是一个常量定义在 limits.h 头文件中 其值就是字面意思
#define Min(a,b) ((a)<(b)?(a):(b))//手打min提高效率
#define Max(a,b) ((a)>(b)?(a):(b))//同上,切记括号千万不能漏
//STL 中的 max 和 min 速度相当慢 用 if 速度也不及条件表达式
using namespace std;
inline int read()//快读不解释
{
char c=getchar();
int x=0,fh=0;
while(c<'0'||c>'9'){fh|=c=='-';c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return fh?-x:x;
}
int n=r;
int a[101][101];//邻接矩阵存图
int b[100000000];
int main()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j)a[i][j]=lnf;//预处理
for(int i=1;i<n;i++)
{
int x=r,y=r;
a[x][y]=1;//父亲到孩子距离为1
a[y][x]=2;//孩子到父亲距离为2
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j]=Min(a[i][j],a[i][k]+a[k][j]);//Floyd算法
int u=r,v=r;
int maxsum=0,maxd=0,maxn=1;
for(int i=2;i<=n;i++)
{
maxsum=Max(maxsum,a[1][i]);//深度
b[a[1][i]]++;//同时统计每一层的节点数
maxn=Max(maxn,a[i][1]);
}
for(int i=1;i<=maxn;i++)
maxd=Max(maxd,b[i]);//宽度
cout<<maxsum+1<<endl;
cout<<maxd<<endl;
cout<<a[u][v]<<endl;//树上距离
return 0;
}