树的直径的两种求法

打多校才发现连树的直径都忘了,赶紧来复习一下树的直径
这里只讲裸的树的直径..
有两种常见的方法去求树的直径

树形dp写法:

第一种是树形dp,我们随便选个结点作为根将有根树转化为无根树,用dp[x]表示以x为根的子树中从x出发的最长链的长度,如果Yi是x的儿子们,那么状态转移是这样的dp[x]=max(dp[x],dp[y]+Edge),接下来考虑经过x的最长链的长度f[x],那么max(f[i],1<=i<=n)就是树的直径了,假设yi,yj是x的两个直接相连的结点,那么f(x)=max(dp[yi]+dp[yj]+x与yi,yj的距离)

具体实现就在下面了

#include <bits/stdc++.h>
using namespace std;
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i < n; i++)
#define per(i, a, n) for (int i = n - 1; i >= a; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef vector<int, int> VII;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 1e3 + 7;
const ll MAXM = 1e5 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-6;
const double pi = acos(-1.0);
int n, m;
struct Edge
{
    int from, to, val;
    int next;
} E[MAXM];
int cnt = -1;
int ans = -inf;
int head[MAXN];
int dp[MAXN]; /* dp[x]表示从结点x出发,往以x作为根的子树走,能够到达的最远距离 */
void add(int from, int to, int val)
{
    E[++cnt].from = from;
    E[cnt].to = to;
    E[cnt].val = val;
    E[cnt].next = head[from];
    head[from] = cnt;
}
void init()
{
    ans = -inf;
    cnt = -1;
    memset(head, -1, sizeof(head));
    memset(dp, 0, sizeof(dp));
}
/* 求树的直径 */
void tree_dp(int u, int fa) /* 随便选个结点作为根结点把树转换成有根树 */
{
    for (int i = head[u]; i != -1; i = E[i].next)
    {
        int to = E[i].to;
        if (fa == to)
            continue;
        tree_dp(to, u);
        ans = max(ans, dp[u] + dp[to] + E[i].val);
        dp[u] = max(dp[u], dp[to] + E[i].val);
    }
}
int main()
{
    init();
    cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        int u, v, val;
        cin >> u >> v >> val;
        add(u, v, val); //建边
        add(v, u, val);
    }
    tree_dp(1, -1);
    cout << ans << endl;
    return 0;
}

两次dfs或者bfs:

这样写还方便计算出直径上的具体结点。
第一次dfs从任意结点出发对树进行遍历,求出与出发点距离最远的结点记为x
那么从x出发,通过第二次dfs在进行一次遍历,求出与x距离最远的结点y,该结点与结点x得路径长度就是树的直径,这个方法是显然正确的,x肯定是直径的一端,y就是另一端,相连就是树的直径
bfs也差不多...但是不是很想写...

两次dfs具体实现

#include <bits/stdc++.h>
using namespace std;
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i < n; i++)
#define per(i, a, n) for (int i = n - 1; i >= a; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef vector<int, int> VII;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 1e3 + 7;
const ll MAXM = 1e5 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-6;
const double pi = acos(-1.0);
int n, m;
struct Edge
{
    int from, to, val;
    int next;
} E[MAXM];
int cnt = -1;
int ans = -inf;
int head[MAXN];
int vis[MAXN];
int dis[MAXN];
void add(int from, int to, int val)
{
    E[++cnt].from = from;
    E[cnt].to = to;
    E[cnt].val = val;
    E[cnt].next = head[from];
    head[from] = cnt;
}
void init()
{
    ans = -inf;
    cnt = -1;
    memset(head, -1, sizeof(head));
    memset(vis, 0, sizeof(vis));
    memset(dis, 0, sizeof(dis));
}
/* 求树的直径 */
void dfs(int u)
{
    vis[u] = 1;
    for (int i = head[u]; i != -1; i = E[i].next)
    {
        int to = E[i].to;
        if (vis[to])
            continue;
        dis[to] = dis[u] + E[i].val;
        dfs(to);
    }
    return;
}
int main()
{
    init();
    cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        int u, v, val;
        cin >> u >> v >> val;
        add(u, v, val); //建边
        add(v, u, val);
    }
    dfs(1); /* 第一遍dfs */
    int maxx = -inf, start = -1;
    for (int i = 1; i <= n; i++)
    {
        if (dis[i] > maxx)
        {
            maxx = dis[i];
            start = i;
        }
        dis[i] = vis[i] = 0;
    }
    dfs(start); /* 第二遍dfs */
    for (int i = 1; i <= n; i++)
        ans = max(dis[i], ans);
    cout << ans << endl;
    return 0;
}
/* 7 6
1 2 1
1 3 4
2 4 2
2 5 3
3 6 5
3 7 6 */

转载于:https://www.cnblogs.com/graytido/p/11258010.html

### 计算木枝干直径的方法 在计算木枝干的直径时,可以采用几何建模和物理模拟相结合的方式。以下是几种可能的技术路径: #### 几何建模方法 如果目标是在虚拟环境中生成一棵,则可以通过定义参数化模型来控制枝干的直径。Unity3D 提供了一个内置的编辑器工具[^2],允许用户从主干开始构建整棵,并调整各部分的比例关系。在这种情况下,枝干的直径可以直接作为输入参数设置。 对于更复杂的场景,还可以引入基于分形理论或者L-System的语言描述法来自动生成自然形态的植物结构。这些方法通常会考虑生长规律以及环境因素的影响,在此过程中也会涉及对不同层次分支粗细比例的设计。 #### 物理仿真方法 当需要更加真实地表现风吹草动下的动态效果时,就需要运用物理学原理来进行数值分析了。文献提到过一种假设条件:“我们简化地假定木的动力学特性”,其中包括一致性的密度分布、忽略掉局部间相互干扰(如无碰撞检测)[^3]等设定前提下推导出来的公式可用于估算实际物体尺寸大小范围内的合理近似值。 具体而言,为了得到某个特定位置处横截面积A(x),可以根据质量守恒定律得出相应长度l上的变化趋势dA/dx=-k*A^n其中n>=1取决于材料属性等因素;而最终求得半径r即满足π*r²=A即可完成整个流程操作步骤说明完毕之后再给出一段总结性质的话收尾比较好一点吧比如下面这样写就不错哦~ 另外值得注意的是上述两种途径各有优劣之处需视具体情况灵活选用合适方案解决问题才是王道呢! ```python import math def calculate_diameter(mass, length, constant_k=0.5): """ Calculate the diameter of a tree branch based on mass and length. Parameters: mass (float): Mass per unit length of the branch. length (float): Length of the segment along which to compute the radius change. constant_k (float): Empirical coefficient related to material properties. Returns: float: Diameter at end point after specified distance traveled through growth process. """ initial_area = 4 * math.pi ** 2 / (constant_k**(1/2)) # Simplified assumption about starting condition final_area = ((initial_area)**(-constant_k*length)+mass)*((initial_area)**constant_k)-mass return math.sqrt(final_area/math.pi) example_result = calculate_diameter(1e-3, 5) print(f"The calculated diameter is approximately {round(example_result, 6)} meters.") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值