树的直径
定义:树的直径为树中最远的两个节点的距离之和。在求树的直径时一般有两种方法:树形dp或则两个BFS(DFS也可以)。
1.树形dp求解树的直径
思路:由树的直径定义可知:其树形dp的状态转移方程为:
[D[x]=max(D[y_i]+Edge(x_i,y_i))
]
其中D[x]表示从节点x出发走向以x为根的子树,能够到达的最远距离。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct node
{
int nex,to,val;
}edge[maxn];
int head[maxn],dis[maxn],v[maxn],n,s,res=0,tot=0;
void add(int from,int to,int val)
{
edge[++tot].to=to;
edge[tot].val=val;
edge[tot].nex=head[from];
head[from]=tot;
}
void dp(int x)
{
v[x]=1;
for(int i=head[x];i!=-1;i=edge[i].nex)
{
int y=edge[i].to;
if(v[y]) continue;
dp(y);
res=max(res,dis[x]+dis[y]+edge[i].val);
dis[x]=max(dis[x],dis[y]+edge[i].val);
}
}
int main()
{
scanf("%d%d",&n,&s);
memset(head,-1,sizeof(head));
for(int i=1;i<n;++i)
{
int a,b,val;
scanf("%d%d%d",&a,&b,&val);
add(a,b,val);
add(b,a,val);
}
dp(s);
printf("%d
",res);
system("pause");
}
2.两次BFS求解树的直径
两次DFS或者BFS也可以求得树的直径,并且更容易的计算出直径上的具体结点。
3.两次DFS求解树的直径
如需求具体方案,只需在第二次dfs的时候记录一下即可,show code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int inf=0x3f3f3f3f;
struct node
{
int nex,to,val;
}edge[maxn];
int head[maxn],tot=0,n,m,dis[maxn],res;
bool v[maxn];
int start,ed;
inline void add(int from,int to,int val)
{
edge[++tot].to = to;
edge[tot].val=val;
edge[tot].nex=head[from];
head[from]=tot;
}
void dfs(int x)
{
v[x]=1;
for(int i=head[x];i!=-1;i=edge[i].nex){
int y=edge[i].to;
if(v[y]) continue;
dis[y]=dis[x]+edge[i].val;
dfs(y);
}
}
int main()
{
memset(v,0,sizeof(v));
memset(head,-1,sizeof(head));
scanf("%d %d",&n,&m);
for(int i=1;i<=m;++i){
int a,b,val;
scanf("%d %d %d",&a,&b,&val);
add(a,b,val);
add(b,a,val);
}
for(int i=1;i<=n;++i)
dis[i]=(i==1)?0:inf;
dfs(1); //找到树的一个端点
res=0;
for(int i=1;i<=n;++i)
if(dis[i]>res&&dis[i]!=inf){
res=dis[i]; //找到1的一个最远的端点,start确定
start=i;
}
memset(v, 0, sizeof(v)); //注意重新初始化
for(int i=1;i<=n;++i)
dis[i]=(i==start)?0:inf;
dfs(start);
res=0; //找到离端点最远的结点,距离即为直径
for(int i=1;i<=n;++i)
if(dis[i]>res&&dis[i]!=inf){
res=dis[i];
ed=i;
}
printf("%d
",res);
}