zoukankan      html  css  js  c++  java
  • bzoj 4326: NOIP2015 运输计划

    4326: NOIP2015 运输计划

    Time Limit: 30 Sec Memory Limit: 128 MB

    Description

    公元 2044 年,人类进入了宇宙纪元。L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球。小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之间不会产生任何干扰。为了鼓励科技创新, L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后,这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的物流公司的阶段性工作就完成了。如果小 P 可以自由选择将哪一条航道改造成虫洞, 试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?

    Input

    第一行包括两个正整数 n,m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 1 到 n 编号。接下来 n−1 行描述航道的建设情况,其中第 i 行包含三个整数 ai,bi 和 ti,表示第 i 条双向航道修建在 ai 与 bi 两个星球之间,任意飞船驶过它所花费的时间为 ti。数据保证 1≤ai,bi≤n 且 0≤ti≤1000。接下来 m 行描述运输计划的情况,其中第 j 行包含两个正整数 uj 和 vj,表示第 j 个运输计划是从 uj 号星球飞往 vj号星球。数据保证 1≤ui,vi≤n

    Output

    输出文件只包含一个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。

    Sample Input

    6 3

    1 2 3

    1 6 4

    3 1 7

    4 3 6

    3 5 5

    3 6

    2 5

    4 5

    Sample Output

    11

    题目分析

    当初联赛此题我看都来得及没看,好弱啊。当初听学长说此题是一道树剖,本蒟蒻现在学了树剖还是不会。

    首先,此题要求最大值最小,容易可以想到二分。

    现在要想如何(check)

    显然,要变为虫洞的边应该在所有比(mid)值大的路径上,于是我们需要快速求出所有这类路径的交集上的最大边。

    我们可以用差分来进行求交集,之后乱搞一下就好了。

    代码比较丑,用时8500ms+

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    //Input
    int ina; char inc,inb[1<<16],*ine=inb,*ins=inb;
    #define getc() ((ins==ine&&(ine=(ins=inb)+fread(inb,1,1<<16,stdin),ins==ine))?EOF:*ins++)
    inline int geti() {
        while((inc=getc())<'0'||inc>'9'); ina=inc-'0';
        while((inc=getc())>='0'&&inc<='9') ina=(ina<<3)+(ina<<1)+inc-'0';
        return ina;
    }
    //Tree
    #define N 300010
    int son[N],fa[N],top[N],head[N],nxt[N<<1],to[N<<1],w[N<<1],tote,dep[N],dis[N],d[N];
    #define FOR(a,b) for(int a=head[b];~a;a=nxt[a])
    int dfs1(int u) {
        int ret=1,t,mx=0; son[u]=0;
        FOR(i,u) if(to[i]^fa[u]) {
            dep[to[i]]=dep[u]+1;
            dis[to[i]]=dis[u]+w[i];
            fa[to[i]]=u;
            ret +=(t=dfs1(to[i]));
            (mx<t)?mx=t,son[u]=to[i]:1;
        }
        return ret;
    }
    void dfs2(int u,int tp) {
        top[u]=tp; if(son[u]) dfs2(son[u],tp);
        FOR(i,u) if(to[i]!=fa[u]&&to[i]!=son[u])
            dfs2(to[i],to[i]);
    }
    int lca(int u,int v) {
        while(top[u]^top[v]) {
            if(dep[top[u]]<dep[top[v]]) u^=v^=u^=v;
            u=fa[top[u]];
        }
        return (dep[u]<dep[v])?u:v;
    }
    //Operator
    int From[N],End[N],Len[N],Lca[N];
    //main
    int mxdis,mxedge,cntmor,val[N],n,m;
     
    int rejudge(int u) {
        FOR(i,u) if(to[i]^fa[u]) d[u]+=rejudge(to[i]);
        (d[u]==cntmor&&mxedge<val[u])?mxedge=val[u]:1;
        return d[u];
    }
     
    bool check(int x) {
        mxdis=mxedge=cntmor=0;
        memset(d,0,sizeof d);
        for(int i=1;i<=m;++i) if(Len[i]>x) {
            (mxdis<Len[i])?mxdis=Len[i]:1;
            ++d[From[i]],++d[End[i]];
            d[Lca[i]]-=2; ++cntmor;
        }
        rejudge(1);
        return mxdis-mxedge<=x;
    }
     
    int main() {
        int i,j,k,a,b,c,l,r=0,mid,ans;
        memset(head,-1,sizeof head);
        for(n=geti(),m=geti(),i=1;i<n;++i) {
            a=geti(),b=geti(),c=geti();
            to[tote]=b,nxt[tote]=head[a],w[tote]=c,head[a]=tote++;
            to[tote]=a,nxt[tote]=head[b],w[tote]=c,head[b]=tote++;
        }
        dfs1(1), dfs2(1,1);
        for(i=0;i<tote;i+=2) val[(dep[to[i]]<dep[to[i^1]])?to[i^1]:to[i]]=w[i];
        for(i=1;i<=m;++i) {
            From[i]=geti(),End[i]=geti();
            Len[i]=dis[From[i]]+dis[End[i]]-2*dis[Lca[i]=lca(From[i],End[i])];
            (r<Len[i])?r=Len[i]:1;
        }
        l=0;
        while(l<=r) {
            mid=l+r>>1;
            if(check(mid)) r=(ans=mid)-1;
            else l=mid+1;
        }
        return printf("%d
    ",ans),0;
    }
    

    update:

    此代码在洛谷(被某人刷贴之后管理员改时限过了)和CodeVs(非官方数据)上被卡掉了,似乎用tarjan可过,不过不想改了。

  • 相关阅读:
    Kvm --01 虚拟化基础概念
    Git--09 创建Maven项目
    Git--08 Jenkins
    Git--07 Gitlab备份与恢复
    Git --06 Git-gui安装
    Git --05 Gitlab使用
    Git--04 Github使用
    socket 释放全过程
    动态规划习题总结
    linux heap堆分配
  • 原文地址:https://www.cnblogs.com/cycleke/p/5952127.html
Copyright © 2011-2022 走看看