zoukankan      html  css  js  c++  java
  • [2019.1.3]BZOJ4326 NOIP2015 运输计划

    看到最大值最小,第一个想到二分答案。

    那么我们需要改成虫洞的边必然被所有大于当前答案的路径覆盖,我们只要在这些边中找到一条时间最大的,看看删去以后能否使之前耗时最长的路径耗时小于等于答案就好了。

    那么如何找到满足条件的边呢?

    我们可以将每一条超出答案的路径上所有的边打上一个标记,(标记数量=超出答案的边的数量)的边即是满足条件的边。

    但是暴力打标记就T了。

    所以我们要树上差分。

    然后就可以了。

    洛谷卡常,卡了好几天过不去,直到某一个神仙(orz)换上了他的码风才过去(神仙的码风快我两倍以上orz)。

    大致就是从

    倍增LCA+vector存图+自己码风+无fread+O2=(color{blue} exttt{TLE})

    变成

    树剖LCA+vector存图+自己码风+fread+无O2(开了就MLE不知为什么)=(color{blue} exttt{TLE})

    然后

    树剖LCA+链式前向星存图+自己码风+fread+无O2(开了就全TLE不知为什么)=(color{blue} exttt{TLE})

    最后

    树剖LCA+链式前向星存图+神仙码风+fread+无O2=(color{green} exttt{AC})

    提交记录

    code:

    神仙码风可读性差,还是放了自己的码风,AC代码在后面

    (自己的码风可读性也不高嘛...)

    #include<bits/stdc++.h>
    using namespace std;
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    char buf[1<<21],*p1=buf,*p2=buf;
    struct edge{
        int t,w,nxt;
    }e[600010];
    struct Path{
        int a,b,lca,len;
    }p[300010];
    int n,m,u,v,t,beg[300010],cnt,lg,vis[300010],f[300010],tp[300010],sz[300010],sum[300010],dep[300010],l,r,mid,siz,s[300010],mxe,mxl;
    void add(int x,int y,int val){
        e[++cnt].t=y;
        e[cnt].w=val;
        e[cnt].nxt=beg[x];
        beg[x]=cnt;
    }
    int Dfs(int x){
        vis[x]=1;
        sz[x]=1;
        for(int i=beg[x];i;i=e[i].nxt)if(!vis[e[i].t])dep[e[i].t]=dep[x]+1,sum[e[i].t]=sum[x]+e[i].w,sz[x]+=Dfs(e[i].t);else f[x]=e[i].t;
        return sz[x];
    }
    int Dfs2(int x){
        int mxs=0,d=0;
        for(int i=beg[x];i;i=e[i].nxt)if(e[i].t!=f[x]&&sz[e[i].t]>mxs)mxs=sz[e[i].t],d=e[i].t;
        if(d)tp[d]=tp[x],Dfs2(d);
        for(int i=beg[x];i;i=e[i].nxt)if(e[i].t!=f[x]&&e[i].t!=d)tp[e[i].t]=e[i].t,Dfs2(e[i].t);
    }
    int LCA(int x,int y){
        while(tp[x]!=tp[y]){
            if(dep[tp[x]]<dep[tp[y]])swap(x,y);
            x=f[tp[x]];
        }
        if(dep[y]<dep[x])return y;
        return x;
    }
    int dfs(int x){
        int tot=s[x],tfe=0;
        for(int i=beg[x];i;i=e[i].nxt)if(e[i].t!=f[x])tot+=dfs(e[i].t);else tfe=e[i].w;
        if(tot==siz)mxe=max(mxe,tfe);
        return tot;
    }
    bool check(int x){
        mxe=mxl=siz=0;
        memset(s,0,sizeof(s));
        for(int i=1;i<=m;i++)if(p[i].len>x)s[p[i].a]++,s[p[i].b]++,s[p[i].lca]-=2,mxl=max(mxl,p[i].len),siz++;
        dfs(1);
        return mxl-mxe<=x;
    }
    void scan(int &x){
        x=0;
        char c=getchar();
        while('0'>c||c>'9')c=getchar();
        while('0'<=c&&c<='9')x=x*10+c-'0',c=getchar();
    }
    int main(){
        scan(n),scan(m);
        for(int i=1;i<n;i++)scan(u),scan(v),scan(t),add(u,v,t),add(v,u,t);
        dep[1]=1;
        Dfs(1);
        tp[1]=1;
        Dfs2(1);
        for(int i=1;i<=m;i++)scan(p[i].a),scan(p[i].b),p[i].lca=LCA(p[i].a,p[i].b),p[i].len=sum[p[i].a]+sum[p[i].b]-2*sum[p[i].lca],r=max(r,p[i].len);
        while(l<r){
            mid=(l+r)/2;
            if(check(mid))r=mid;
            else l=mid+1;
        }
        printf("%d",l);
        return 0;
    }
    

    神仙码风:

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    #define add(x,y,val) (e[++cnt].t=y,e[cnt].w=val,e[cnt].nxt=beg[x],beg[x]=cnt)
    #define swap(x,y) (x^=y^=x^=y)
    char buf[1<<21],*p1=buf,*p2=buf;
    struct edge{
        int t,w,nxt;
    }e[600010];
    struct Path{
        int a,b,lca,len;
    }p[300010];
    int n,m,u,v,t,beg[300010],cnt,lg,vis[300010],f[300010],tp[300010],sz[300010],sum[300010],dep[300010],l,r,mid,siz,s[300010],mxe,mxl;
    int Dfs(int x){
        vis[x]=1,sz[x]=1;
        for(register int i=beg[x];i;i=e[i].nxt) vis[e[i].t]?(f[x]=e[i].t):(dep[e[i].t]=dep[x]+1,sum[e[i].t]=sum[x]+e[i].w,sz[x]+=Dfs(e[i].t));
        return sz[x];
    }
    void Dfs2(int x){
        register int i,mxs=0,d=0;
        for(i=beg[x];i;i=e[i].nxt) e[i].t^f[x]&&sz[e[i].t]>mxs&&(mxs=sz[e[i].t],d=e[i].t);
        for(d&&(tp[d]=tp[x],Dfs2(d),0),i=beg[x];i;i=e[i].nxt) e[i].t^f[x]&&e[i].t^d&&(tp[e[i].t]=e[i].t,Dfs2(e[i].t),0);
    }
    inline int LCA(int x,int y){
        while(tp[x]^tp[y]) dep[tp[x]]<dep[tp[y]]&&swap(x,y),x=f[tp[x]];
        return dep[y]<dep[x]?y:x;
    }
    int dfs(int x){
        register int i,tot=s[x],tfe=0;
        for(i=beg[x];i;i=e[i].nxt) e[i].t^f[x]?tot+=dfs(e[i].t):tfe=e[i].w;
        return tot==siz&&(mxe<tfe)&&(mxe=tfe),tot;
    }
    inline bool check(int x){
        mxe=mxl=siz=0,memset(s,0,sizeof(s));
        for(register int i=1;i<=m;++i) p[i].len>x&&(++s[p[i].a],++s[p[i].b],s[p[i].lca]-=2,mxl=max(mxl,p[i].len),++siz);
        return dfs(1),mxl-mxe<=x;
    }
    inline void scan(int &x){
        x=0;
        register char c=getchar();
        while(!isdigit(c))c=getchar();
        while(isdigit(c))x=(x<<3)+(x<<1)+(c&15),c=getchar();
    }
    int main(){
        register int i;
        for(scan(n),scan(m),i=1;i<n;++i)scan(u),scan(v),scan(t),add(u,v,t),add(v,u,t);
        for(dep[1]=1,Dfs(1),tp[1]=1,Dfs2(1),i=1;i<=m;i++)scan(p[i].a),scan(p[i].b),p[i].lca=LCA(p[i].a,p[i].b),p[i].len=sum[p[i].a]+sum[p[i].b]-(sum[p[i].lca]<<1),r<p[i].len&&(r=p[i].len);
        while(l<r)check(mid=l+r>>1)?r=mid:l=mid+1;
        return printf("%d",l),0;
    }
    
  • 相关阅读:
    2017-3-28 javaScript DOM 操作
    2017-3-28 JavaScript 基础、语法
    2017-3-25 CSS 样式表(二)
    js判断文件是否存在的方法
    关于eclipse添加自动查找文件以及svn的插件
    关于jqgrid的一些使用
    ztree框架使用问题汇总
    bootstrap框架的使用
    UIButton 设置阴影效果
    xcode升级至9.0之后,新建xib报错: Safe Area Layout Guide Before IOS 9.0
  • 原文地址:https://www.cnblogs.com/xryjr233/p/BZOJ4326.html
Copyright © 2011-2022 走看看