【BZOJ】3246 [Ioi2013]Dreaming

来源:互联网 发布:怎么注册邮箱登录淘宝 编辑:程序博客网 时间:2024/05/17 23:13

传送门: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 500005int 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
原创粉丝点击