【BZOJ】3246 [Ioi2013]Dreaming

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3246

很容易想到是连接各树重心
处理每棵树直径和最大深度,连接后的树的直径会由以下三方面贡献:
原本的直径
最深树和次深树构成的直径
次深树和次次深树构成的直径

(写给我自己的注意事项:一个儿子只能贡献最长链或者次长链中的一个)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define cint const int &
#define inf 1000000000000000000LL
#define N 500005

int tot,s[N],f[N],n,m,L;
ll d1[N],d2[N],mn,ans;
priority_queue<ll> Q;

struct edge{int v,c,n;}e[N<<1];
inline void push(cint u,cint v,cint c){e[++tot]=(edge){v,c,s[u]};s[u]=tot;}
#define Push(u,v,c) push(u,v,c),push(v,u,c);

void down(cint k,cint fa=-1)
{
    f[k]=fa;
    for (int i=s[k];i;i=e[i].n) if (!f[e[i].v])
    {
        down(e[i].v,k);
        if (d1[k]<=d1[e[i].v]+e[i].c) d2[k]=d1[k],d1[k]=d1[e[i].v]+e[i].c;
        else d2[k]=max(d2[k],d1[e[i].v]+e[i].c);
    }
    ans=max(ans,d1[k]+d2[k]);
}

void up(cint k,const ll &u=0)
{
    mn=min(mn,max(u,d1[k]));ans=max(ans,u+d1[k]);
    for (int i=s[k];i;i=e[i].n) if (e[i].v!=f[k]) up(e[i].v,max(u,(d1[e[i].v]+e[i].c==d1[k]?d2[k]:d1[k]))+e[i].c);
}

inline void pre(cint k)
{
    down(k);
    mn=inf;
    up(k);
    Q.push(mn);
}

int main()
{
    scanf("%d%d%d",&n,&m,&L);
    for (int i=1,u,v,c;i<=m;++i)
    {
        scanf("%d%d%d",&u,&v,&c);
        Push(u+1,v+1,c);
    }
    for (int i=1;i<=n;++i) if (!f[i]) pre(i);
    ll k1=-inf/2,k2=-inf/2,k3=-inf/2;
    if (!Q.empty()) k1=Q.top(),Q.pop();
    if (!Q.empty()) k2=Q.top(),Q.pop();
    if (!Q.empty()) k3=Q.top(),Q.pop();
    printf("%lld",max(ans,max(k1+k2+L,k2+k3+L*2)));
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值