• 逃学的小孩,树形dp


    先找到

    题意:

      中文题,没什么好解释的,也没什么歧义。

    分析:

      首先我们想一下他的路径将会是怎样的:A-B-C/A-C-B,其实就是求一下min(AB+BC,AC+BC),ABC任选。挺简单,首先证明一点:BC不是直径时不会更优,证明之后,我们就可以直接找到直径,然后遍历每个点,实在是有点简单了,也没啥细节。

      还可以这么想:他的路径是这样的:A-O-B-O-C/A-O-C-O-B,及他是由三段组成的,枚举点O(可以理解成二次元换根,或者说就是两遍dfs)计算最长的三段,求max(ma1+ma2*2+ma3)就好了。也是过于简单。最后就是代码。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=200000+10;
    int head[maxn];
    struct E{
        int to;
        int next;
        long long val;
        E(){
            to=next=val=0;
        }
    }ed[maxn*2];
    int tot;
    void J(int a,int b,long long c){
        tot++;
        ed[tot].to=b;
        ed[tot].val=c;
        ed[tot].next=head[a];
        head[a]=tot;
    }
    long long ma1[maxn];
    long long ma2[maxn];
    long long ans;
    int jl;
    long long j1[maxn];//记录到两段的距离
    long long j2[maxn];
    int m1a[maxn];//记录节点
    int m2a[maxn];
    void Dfs1(int x,int fa){
        m1a[x]=m2a[x]=x;//初始化,
        int js=0;
        for(int i=head[x];i;i=ed[i].next){
            if(ed[i].to==fa)
                continue;
            js++;
            Dfs1(ed[i].to,x);
            ma2[x]=max(ma2[x],ed[i].val+ma1[ed[i].to]);
            if(ma2[x]==ed[i].val+ma1[ed[i].to])
                m2a[x]=m1a[ed[i].to];
            if(ma2[x]>ma1[x]){
                swap(ma2[x],ma1[x]);
                swap(m2a[x],m1a[x]);
            }
        }
        ans=max(ma1[x]+ma2[x],ans);
        if(ma1[x]+ma2[x]==ans)
            jl=x;
        if(!js)
            m1a[x]=m2a[x]=x;
    }
    void Dfs2(int x,int fa){
        for(int i=head[x];i;i=ed[i].next){
            if(ed[i].to==fa)
                continue;
            j1[ed[i].to]=j1[x]+ed[i].val;
            Dfs2(ed[i].to,x);
        }
    }
    void Dfs3(int x,int fa){
        for(int i=head[x];i;i=ed[i].next){
            if(ed[i].to==fa)
                continue;
            j2[ed[i].to]=j2[x]+ed[i].val;
            Dfs3(ed[i].to,x);
        }
    }
    int main(){
        int n,m;
        scanf("%d%d",&n,&m);
        int js1,js2;
        long long js3;
        for(int i=1;i<=m;i++){
            scanf("%d%d%lld",&js1,&js2,&js3);
            J(js1,js2,js3);
            J(js2,js1,js3);
        }
        Dfs1(1,0);
        Dfs2(m1a[jl],0);
        Dfs3(m2a[jl],0);
        long long p=0;
        for(int i=1;i<=n;i++)
            p=max(p,min(j1[i],j2[i])+ans);
        printf("%lld",p);
        return 0;
    }
  • 相关阅读:
    洛谷 P1119 灾后重建
    [NOIP 2011] 观光公交
    AtCoder Beginner Contest 071 D
    UOJ #228. 基础数据结构练习题
    bzoj 3673&3674: 可持久化并查集 by zky
    bzoj 2427: [HAOI2010]软件安装
    都市环游
    poj2299——Ultra-QuickSort
    poj1958——Strange Towers of Hanoi
    洛谷 P4139 上帝与集合的正确用法
  • 原文地址:https://www.cnblogs.com/wish-all-ac/p/12659136.html
Copyright © 2020-2023  润新知