树的直径
定义
一个树的直径就是树上两个点的距离中最长的距离。
性质
-
树的直径的路径不一定唯一。
-
树的端点一定是度数为
的点。 -
树的直径若有多条,则一定交汇于数的中心(以这个点为根,树的最大深度最小)。
-
树上任意点
,距离 最远的点,一定是树的直径的端点之一。
求法
-
Floyd 暴力求索。
-
两遍 DFS,利用性质
,从任意一个点开始 DFS,找到距离这个点最远的点 ,然后从 开始 DFS,找到最远的点 ,则点 和 为数的直径的两端。不过在取最大值的时候,不能写当前长度大于最大长度,要大于等于,因为后面的可能长度一样,但是点要重新取。
例题
Luogu-B4016
思路
模板题,套上面的思路。
代码
#include <bits/stdc++.h>
using namespace std;
int n, x, mx;
bool vis[100005];
vector<int> g[100005];
void dfs(int u, int sum) {
vis[u] = 1;
if (sum >= mx) {
mx = sum;
x = u;
}
for (int i = 0; i < g[u].size(); ++i) {
int v = g[u][i];
if (!vis[v]) {
dfs(v, sum + 1);
}
}
return;
}
int main() {
cin.tie(0)->sync_with_stdio(false);
cin >> n;
for (int i = 1, x, y; i < n; ++i) {
cin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
dfs(1, 0);
fill(vis + 1, vis + n + 1, 0);
dfs(x, 0);
cout << mx;
return 0;
}
HDU-2196
思路
方法一:
直接暴力 DFS。
方法二:
利用树的直径的性质
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e4+5;
int n,x,mx,a,b,dis[N][2];
bool vis[N];
struct Node{
int v,w;
};
vector<Node> g[N];
void dfs(int u,int sum)
{
vis[u]=1;
if(sum>=mx)
{
mx=sum;
x=u;
}
for(int i=0;i<g[u].size();++i)
{
int v=g[u][i].v,w=g[u][i].w;
if(!vis[v])
{
dfs(v,sum+w);
}
}
return;
}
void dfs2(int u,int f)
{
vis[u]=1;
for(int i=0;i<g[u].size();++i)
{
int v=g[u][i].v,w=g[u][i].w;
if(!vis[v])
{
dis[v][f]=dis[u][f]+w;
dfs2(v,f);
}
}
return;
}
signed main()
{
cin.tie(0)->sync_with_stdio(false);
while(cin>>n)
{
for(int i=1;i<=n;++i)
{
g[i].clear();
vis[i]=0;
dis[i][0]=dis[i][1]=0;
}
a=0,b=0;
for(int i=2,y,z;i<=n;++i)
{
cin>>y>>z;
g[i].push_back({y,z});
g[y].push_back({i,z});
}
mx=0,x=0;
fill(vis+1,vis+n+1,0);
dfs(1,0);
a=x;
fill(vis+1,vis+n+1,0);
dfs(x,0);
b=x;
fill(vis+1,vis+n+1,0);
dfs2(a,0);
fill(vis+1,vis+n+1,0);
dfs2(b,1);
for(int i=1;i<=n;++i)
{
cout<<max(dis[i][0],dis[i][1])<<'\n';
}
}
return 0;
}
Codeforces-734E
思路
我们先将一个颜色且联通的连通块缩成一个点,
然后,此时的树必定是黑白交替的,那么最终的答案就是
注意
两遍 DFS 的做法也有一个缺点,就是不能有负边权。
hack数据:
5
1 2 5
2 4 -10
4 5 20
1 3 4
正确答案:
19
实际输出:
20
树形DP求解
-
树的中心的最长链和次长链对应的端点就是树的直径的两端。
-
维护点
的最长路 和 ,取 即树的直径。 -
除了共点
,两条路径没有交点,树的中心要进行枚举。 -
可以处理负边权。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术