• Luogu_4886 快递员


    Luogu_4886 快递员

    一道淀粉质的题目。

    先考虑最简单的算法,那便是对每个点都求一边。时间复杂度O(NM)

    然后如果我们把每个点的结果对应一个高度,我们会发现。最优解是在这个对应高度形成的三维图像中的谷底(谷缝)

    也就数说,对于一条链来说,他是一个开口向上的类似二次函数的一个图形。

    具有类似单调性的一类性质。

    在O(NM)的算法中,可以使用其剪枝。既是如果相邻的节点的答案要大于当前节点,那么我们就不向那个节点进行搜索。

    为什么? 如果相邻节点的答案小于当前点,那么说明,当前的最长链的两端都在相邻节点所确定的子树中。

    所以我们往这颗子树中走就用可能是更优的。(随时取min)

    为什么说是可能?因为这个最长链的位置可能改动。


    对于这个二次函数图像,我们可以使用一个类似二分的方法,在log时间复杂度中找到最小值。

    就是前文说的类似单调性一样的东西。

    所以我们可以利用最长连所在的子树的重心进行检验。

    因为重心的性质,我们就可以每次将问题至少缩小一半规模。

    至于什么时候退出呢?

    要么递归到底,要么子树重心的答案大于当前最优答案。

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    
    using std::min;
    using std::max;
    
    const int maxn=101000;
    const int inf=0x7fffffff;
    
    struct node
    {
        int p;
        int value;
        int nxt;
    };
    
    node line[maxn<<1];
    int head[maxn],tail;
    int query[maxn][2];
    int vis[maxn],dis[maxn],size[maxn],f[maxn];
    int belong[maxn];
    int n,m,root,sum;
    int ans,where;
    
    int read()
    {
        char c=getchar();
        int res=0;
        while(c>'9'||c<'0') c=getchar();
        while(c>='0'&&c<='9')
        {
            res=(res<<1)+(res<<3)+c-'0';
            c=getchar();
        }
        return res;
    }
    
    void add(int a,int b,int c)
    {
        line[++tail].p=b;
        line[tail].value=c;
        line[tail].nxt=head[a];
        head[a]=tail;
        return ;
    }
    
    void get_dis(int now,int fa,int Dis,int Belong)
    {
        dis[now]=Dis;
        belong[now]=Belong;
        for(int i=head[now];i;i=line[i].nxt)
        {
            int v=line[i].p;
            if(v==fa)    continue;
            get_dis(v,now,Dis+line[i].value,Belong);
        }
        return ;
    }
    
    void get_size(int now,int fa)
    {
        size[now]=1;
        for(int i=head[now];i;i=line[i].nxt)
        {
            int v=line[i].p;
            if(vis[v]||v==fa)   continue;
            get_size(v,now);
            size[now]+=size[v];
        }
        return ;
    }
    
    void get_hry(int now,int fa)
    {
        size[now]=1;f[now]=0;
        for(int i=head[now];i;i=line[i].nxt)
        {
            int v=line[i].p;
            if(vis[v]||v==fa)    continue;
            get_hry(v,now);
            size[now]+=size[v];
            f[now]=max(f[now],size[v]);
        }
        f[now]=max(f[now],sum-size[now]);
        if(f[now]<f[root])  root=now;
        return ;
    }
    
    void solve(int now)
    {
        sum=size[now];
        root=0;
        get_hry(now,0);
        int Max=0,Be=0,cnt=0;
        vis[root]=1;get_size(root,0);
        belong[root]=dis[root]=0;
        for(int i=head[root];i;i=line[i].nxt)
            get_dis(line[i].p,root,line[i].value,++cnt);
        for(int i=1;i<=m;i++)
            Max=max(Max,dis[query[i][0]]+dis[query[i][1]]);
        ans=min(ans,Max);
    //    if(ans>Max)
    //    {
    //        ans=Max;
    //        where=root;
    //    }
        for(int i=1;i<=m;i++)
        {
            int A=query[i][0],B=query[i][1];
            if(dis[A]+dis[B]!=Max)  continue;
            if(belong[A]==belong[B]&&(!Be||Be==belong[A]))
                Be=belong[A];
            else    if((!belong[A]||!belong[B])&&(!Be||Be==belong[A]+belong[B]))
                Be=belong[A]+belong[B];
            else    return ;
        }
        for(int i=head[root];i;i=line[i].nxt)
            if(!vis[line[i].p]&&Be==belong[line[i].p])
            {
                solve(line[i].p);
                return ;
            }
        return ;
    }
    
    int main()
    {
        n=read();m=read();
        for(int i=1,a,b,c;i<n;i++)
        {
            a=read();b=read();c=read();
            add(a,b,c);
            add(b,a,c);
        }
        for(int i=1;i<=m;i++)
            query[i][0]=read(),query[i][1]=read();
        f[0]=inf;size[1]=n;ans=inf;
        solve(1);
        printf("%d",ans);
        //printf("
    %d",where);
    }
    
    
  • 相关阅读:
    Struts2的配置中:Could not find action or result 问题的解决方法
    Oracle 数据库 Record is locked by another user 问题解决办法
    设计模式六大原则(2):里氏替换原则
    在PL/SQL中 自动复制转换StringBuffer的SQL
    反射setAccessible()方法
    对允许任意图片上传的发布内容模式的啊哈的想法
    如果你真的想做一件事,你一定会找到一个方法;如果你不想做一件事,你一定会找到一个借口.
    xaml 的 intellisense失效的解决办法
    Blog技术词汇之Rss篇 什么是Rss以及其定义[翻译]
    多个存储过程之间相互调用的原子性问题
  • 原文地址:https://www.cnblogs.com/Lance1ot/p/10293284.html
Copyright © 2020-2023  润新知