TyvjP1520 树的直径(模板)

119 篇文章 4 订阅
32 篇文章 0 订阅

题目链接

分析:
我曾经谈过树的直径
但是只停留在理论阶段,不会实现
今天就来填这个史前巨坑

我在blog提到过:
设计状态:
f[i]表示i这棵子树中经过i的最长路径(可以经过i也可以是i作为途中一点)
g[i]表示i这棵子树中,以i为端点的最长路径

f[fa]=max(firstmax{w(fa,u)+g[u]},0)+max(secondmax{w(fa,u)+g[u]},0)
g[fa]=max{w(fa,u)+g[u]}

然而我发现如果真的按照上述的方程转移的话,就很tomato难受
我们可以简化一下状态:
f[i]表示i这棵子树中,以i为端点的最长链
g[i]表示i这棵子树中,以i为端点的次长链
转移的时候,用“每一棵子树的最长链+子树和父亲的连边”来更新父亲的f和g数组
这样当前点对答案的贡献就是f[i]+g[i]

复杂度:O(n)

这里写图片描述

这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

const int N=100010;
int f[N],g[N];
struct node{
    int x,y,nxt,v;
};
node way[N<<1];
int st[N],tot=0,ans=0,n;

void add(int u,int w,int z)
{
    tot++;
    way[tot].x=u;way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;
}

void dfs(int now,int fa)
{
    g[now]=0; f[now]=0;
    for (int i=st[now];i;i=way[i].nxt)
        if (way[i].y!=fa)
        {
            dfs(way[i].y,now);
            int len=way[i].v+f[way[i].y];
            if (len>f[now])
            {
                g[now]=f[now];
                f[now]=len;
            }
            else if (len>g[now])
            {
                g[now]=len;
            }
        }
    ans=max(ans,f[now]+g[now]);
}

int main()
{
    scanf("%d",&n);
    for (int i=1;i<n;i++)
    {
        int u,w,z;
        scanf("%d%d%d",&u,&w,&z);
        add(u,w,z);
        add(w,u,z);
    }
    dfs(1,0);
    printf("%d",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值